FLOSS Project Planets
Bounteous.com: Upgrading to Drupal 10 (And Beyond) With Composer
Bounteous.com: Introduction to ChatOps with Acquia BLT and Slack
Bounteous.com: What’s New in Acquia Site Studio 6.9?
Bounteous.com: Use the Acquia CMS Headless Beta to Improve Headless Applications
Bounteous.com: Building Enterprise Drupal Sites with Acquia Build and Launch Tool (BLT)
Bounteous.com: Drupal 10: Uncovering New Features and Benefits
Bounteous.com: Your Team's Technical Guide to Drupal Code Reviews
Bounteous.com: The Acquia Triple Certification: Distinguishing Yourself as a Drupal Developer
Bounteous.com: PHP 7 to 8: Entering the Modern Era of Programming Languages
Bounteous.com: Our Guide to Upgrading Your Site with Drupal 9
Bounteous.com: Acquia Cloud IDE: First Impressions From a Senior Developer
Localizing spin box prefixes/suffixes
KDE Frameworks 6.5 brings a little new feature for localizing prefix and suffix texts in spin boxes. It’s also a good reminder of the level of detail we have to pay attention to when preparing our software for being translated.
The problemQt spin boxes can have inline prefix and suffix strings. That’s commonly used for units.
There’s multiple challenges when localizing this:
- Plurals: Depending on the selected quantity different plural forms for prefixes/suffixes might be needed (e.g. “1 cake” vs “3 cakes”). How many plural forms there are depends on the language and can be anywhere between none (e.g. Japanese) and six (e.g. Arabic). CLDR’s Language Plural Rules gives you an idea of the complexity.
- Word order: Not all languages place those texts in the same position. For a percent value for example English uses the % sign as a suffix, while Turkish uses it as a prefix.
So just setting a fixed string doesn’t cut it.
Existing solutionsNone of that is new, and for the plural handling we do have an existing solution in form of KPluralHandlingSpinBox in KF::TextWidgets. It takes a suffix in form of a KLocalizedString, which it reevaluates each time its value changes to show the correct plural form.
This works but has a number of downsides:
- It’s not solving the word order problem, and it’s only handing suffixes.
- It’s using inheritance and thus is harder to integrate with custom or otherwise more complex existing spin box code.
- The use of inheritance is also limiting it to QSpinBox, not helping with e.g. QDoubleSpinBox.
Starting with an idea by Emir Sarı and Lukas Sommer for a solution to the word ordering problem and a suggestion by me to generalize the same approach to cover plural handling as well we ended up with two new methods in KF::I18n.
KLocalization::setupSpinBoxFormatString is the one you’ll most commonly need. It allows to set a KLocalizedString format string on any spin box instance. That format string must contain the special placeholder %v, which represents the current spin box value.
Texts before the %v end up in the prefix and the part after it in the suffix, giving translations control over the word order. This can be used both with and without considering plural forms, as shown in the example below.
// with plural QSpinBox spinBox; KLocalization::setupSpinBoxFormatString(&spinBox, ki18np("Baking %v cake", "Baking %v cakes")); // without plural QDoubleSpinBox doubleSpinBox; KLocalization::setupSpinBoxFormatString(&doubleSpinBox, ki18n("%v%"));As this isn’t relying on inheritance it can be used on QSpinBox, QDoubleSpinBox or any subclass thereof. Being part of KF::I18n also means this is very likely available without needing additional dependencies. All of this should help with a much wider adoption than we ever had for KPluralHandlingSpinBox.
The second new method is KLocalization::retranslateSpinBoxFormatString, which explicitly triggers reevaluating the format string. That’s automatically called when the spin box value changes, but if you are for example supporting runtime language changes you might have the need for manually triggering this as well.
What’s left to doWe need to make use of this. It’s an easy way to contribute, and helps making our software better in other languages than English :)
There’s also the question how to address these issues in QML UIs. Qt’ QML spin box control doesn’t have support for inline prefixes/suffixes, but the problems don’t go away by placing the those texts on the outside.
Antoine Beaupré: Why I should be running Debian unstable right now
So a common theme on the Internet about Debian is so old. And right, I am getting close to the stage that I feel a little laggy: I am using a bunch of backports for packages I need, and I'm missing a bunch of other packages that just landed in unstable and didn't make it to backports for various reasons.
I disagree that "old" is a bad thing: we definitely run Debian stable on a fleet of about 100 servers and can barely keep up, I would make it older. And "old" is a good thing: (port) wine and (any) beer needs time to age properly, and so do humans, although some humans never seem to grow old enough to find wisdom.
But at this point, on my laptop, I am feeling like I'm missing out. This page, therefore, is an evolving document that is a twist on the classic NewIn game. Last time I played seems to be #newinwheezy (2013!), so really, I'm due for an update. (To be fair to myself, I do keep tabs on upgrades quite well at home and work, which do have their share of "new in", just after the fact.)
New packages to exploreThose tools are shiny new things available in unstable or perhaps Trixie (testing) already that I am not using yet, but I find interesting enough to list here.
- codesearch: search all of Debian's source code (tens of thousands of packages) from the commandline! (see also dcs-cli, not in Debian)
- dasel: JSON/YML/XML/CSV parser, similar to jq, but different syntax, not sure I'd grow into it, but often need to parse YML like JSON and failing
- fyi: notify-send replacement
- git-subrepo: git-submodule replacement I am considering
- gtklock: swaylock replacement with bells and whistles, particularly interested in showing time, battery and so on
- hyprland: possible Sway replacement, but there are rumors of a toxic community (rebuttal, I haven't reviewed either in detail), so approach carefully)
- ruff: faster Python formatter and linter, flake8/black/isort replacement, alas not mypy/LSP unfortunately, designed to be ran alongside such a tool, which is not possible in Emacs eglot right now, but is possible in lsp-mode
- sfwbar: pretty status bar, may replace waybar, which i am somewhat unhappy with (my UTC clock disappears randomly)
- spytrap-adb: cool spy gear
Those are packages that I have tested because I found them interesting, but ended up not using, but I think people could find interesting anyways.
- kew: surprisingly fast music player, parsed my entire library (which is huge) instantaneously and just started playing (I still use Supersonic, for which I maintain a flatpak on my Navidrome server)
- mdformat: good markdown formatter, think black or gofmt but for markdown), but it didn't actually do what I needed, and it's not quite as opinionated as it should (or could) be)
Those are packages I already use regularly, which have backports or that can just be installed from unstable:
- asn: IP address forensics
- markdownlint: markdown linter, I use that a lot
- poweralertd: pops up "your battery is almost empty" messages
- sway-notification-center: used as part of my status bar, yet another status bar basically, a little noisy, stuck in a libc dep update
- tailspin: used to color logs
Those are packages that are in Debian stable (Bookworm) already, but that are somewhat lacking and could benefit from an upgrade.
- firmware-iwlwifi: out of date, can install from unstable
- fuzzel / foot: log level noises A, B, fuzzel fix not in debian yet, and if we get to 1.11, my scripts in ~/bin should be patched to use --cache
- pandoc: 3.0 is ridiculously huge, but particularly remove spaces after list marker
- podman: better systemd integration
- pubpaste: out of date, can install from unstable
- tremotesf: out of date backport
- undertime: out of date, can install from unstable
- yt-dlp: out of date, can install from unstable
If you know of cool things I'm missing out of, then by all means let me know!
That said, overall, this is a pretty short list! I have most of what I need in stable right now, and if I wasn't a Debian developer, I don't think I'd be doing the jump now. But considering how easier it is to develop Debian (and how important it is to test the next release!), I'll probably upgrade soon.
Previously, I was running Debian testing (which why the slug on that article is why-trixie), but now I'm actually considering just running unstable on my laptop directly anyways. It's been a long time since we had any significant instability there, and I can typically deal with whatever happens, except maybe when I'm traveling, and then it's easy to prepare for that (just pin testing).
Anarcat: Why I should be running Debian unstable right now
So a common theme on the Internet about Debian is so old. And right, I am getting close to the stage that I feel a little laggy: I am using a bunch of backports for packages I need, and I'm missing a bunch of other packages that just landed in unstable and didn't make it to backports for various reasons.
I disagree that "old" is a bad thing: we definitely run Debian stable on a fleet of about 100 servers and can barely keep up, I would make it older. And "old" is a good thing: (port) wine and (any) beer needs time to age properly, and so do humans, although some humans never seem to grow old enough to find wisdom.
But at this point, on my laptop, I am feeling like I'm missing out. This page, therefore, is an evolving document that is a twist on the classic NewIn game. Last time I played seems to be #newinwheezy (2013!), so really, I'm due for an update. (To be fair to myself, I do keep tabs on upgrades quite well at home and work, which do have their share of "new in", just after the fact.)
New packages to exploreThose tools are shiny new things available in unstable or perhaps Trixie (testing) already that I am not using yet, but I find interesting enough to list here.
- codesearch: search all of Debian's source code (tens of thousands of packages) from the commandline! (see also dcs-cli, not in Debian)
- dasel: JSON/YML/XML/CSV parser, similar to jq, but different syntax, not sure I'd grow into it, but often need to parse YML like JSON and failing
- fyi: notify-send replacement
- git-subrepo: git-submodule replacement I am considering
- gtklock: swaylock replacement with bells and whistles, particularly interested in showing time, battery and so on
- hyprland: possible Sway replacement, but there are rumors of a toxic community (rebuttal, I haven't reviewed either in detail), so approach carefully)
- ruff: faster Python formatter and linter, flake8/black/isort replacement, alas not mypy/LSP unfortunately, designed to be ran alongside such a tool, which is not possible in Emacs eglot right now, but is possible in lsp-mode
- sfwbar: pretty status bar, may replace waybar, which i am somewhat unhappy with (my UTC clock disappears randomly)
- spytrap-adb: cool spy gear
Those are packages that I have tested because I found them interesting, but ended up not using, but I think people could find interesting anyways.
- kew: surprisingly fast music player, parsed my entire library (which is huge) instantaneously and just started playing (I still use Supersonic, for which I maintain a flatpak on my Navidrome server)
- mdformat: good markdown formatter, think black or gofmt but for markdown), but it didn't actually do what I needed, and it's not quite as opinionated as it should (or could) be)
Those are packages I already use regularly, which have backports or that can just be installed from unstable:
- asn: IP address forensics
- markdownlint: markdown linter, I use that a lot
- poweralertd: pops up "your battery is almost empty" messages
- sway-notification-center: used as part of my status bar, yet another status bar basically, a little noisy, stuck in a libc dep update
- tailspin: used to color logs
Those are packages that are in Debian stable (Bookworm) already, but that are somewhat lacking and could benefit from an upgrade.
- firmware-iwlwifi: out of date, can install from unstable
- fuzzel / foot: log level noises A, B, fuzzel fix not in debian yet, and if we get to 1.11, my scripts in ~/bin should be patched to use --cache
- pandoc: 3.0 is ridiculously huge, but particularly remove spaces after list marker
- podman: better systemd integration
- pubpaste: out of date, can install from unstable
- tremotesf: out of date backport
- undertime: out of date, can install from unstable
- yt-dlp: out of date, can install from unstable
If you know of cool things I'm missing out of, then by all means let me know!
That said, overall, this is a pretty short list! I have most of what I need in stable right now, and if I wasn't a Debian developer, I don't think I'd be doing the jump now. But considering how easier it is to develop Debian (and how important it is to test the next release!), I'll probably upgrade soon.
Previously, I was running Debian testing (which why the slug on that article is why-trixie), but now I'm actually considering just running unstable on my laptop directly anyways. It's been a long time since we had any significant instability there, and I can typically deal with whatever happens, except maybe when I'm traveling, and then it's easy to prepare for that (just pin testing).
Matt Layman: More Go Standard Library - Building SaaS #198
Reproducible Builds (diffoscope): diffoscope 275 released
The diffoscope maintainers are pleased to announce the release of diffoscope version 275. This version includes the following changes:
[ Chris Lamb ] * Update the test_zip.py text fixtures and definitions to support new changes to IO::Compress. (Closes: #1078050) * Do not call marshal.loads(...) of precompiled Python bytecode as it is inherently unsafe. Replace, at least for now, with a brief summary of the code section of .pyc files. (Re: reproducible-builds/diffoscope#371) * Don't bother to check the Python version number in test_python.py: the fixture for this test is deterministic/fixed. * Update copyright years.You find out more by visiting the project homepage.
ImageX: Bold, Sleek, and Endlessly Customizable: the Gin Theme for Next-Level Drupal Admin Experiences
Authored by Nadiia Nykolaichuk.
Generate Python Bindings for C++ code using Shiboken
This will be a guide on how to generate Python bindings for your C++ library using Shiboken. Shiboken is a tool specifically created to build PySide, so it supports Qt code perfectly fine.
The steps described here require the in-progress merge request that adds the necessary code to Extra CMake Modules. I hope that it gets merged soon (I’ll update the post). I’ll use KUnitConversion as an example, because it’s a small library.
We’ll start adding the building instructions. This part is mostly boilerplate code as it’s the same for any library (except for the obvious thing of changing the library name):
1set(bindings_library "KUnitConversion") 2 3set(wrapped_header ${CMAKE_SOURCE_DIR}/python/bindings.h) 4set(typesystem_file ${CMAKE_SOURCE_DIR}/python/bindings.xml) 5 6set(generated_sources 7 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_module_wrapper.cpp 8 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_wrapper.cpp 9 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_converter_wrapper.cpp 10 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_unit_wrapper.cpp 11 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_unitcategory_wrapper.cpp 12 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_updatejob_wrapper.cpp 13 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_value_wrapper.cpp) 14 15set(qt_libs Qt6::Core) 16 17ecm_generate_python_bindings( 18 PACKAGE_NAME ${bindings_library} 19 VERSION ${KF_VERSION} 20 WRAPPED_HEADER ${wrapped_header} 21 TYPESYSTEM ${typesystem_file} 22 GENERATED_SOURCES ${generated_sources} 23 INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/${KDE_INSTALL_INCLUDEDIR_KF}/KUnitConversion 24 QT_LIBS ${qt_libs} 25 QT_VERSION ${REQUIRED_QT_VERSION} 26 HOMEPAGE_URL "https://invent.kde.org/frameworks/kunitconversion" 27 ISSUES_URL "https://bugs.kde.org/describecomponents.cgi?product=frameworks-kunitconversion" 28) 29 30target_link_libraries(${bindings_library} PRIVATE KF6UnitConversion) 31install(TARGETS ${bindings_library} LIBRARY DESTINATION "${KDE_INSTALL_LIBDIR}/python-kf6")Let’s see what each part does.
1set(bindings_library "KUnitConversion") 2 3set(wrapped_header ${CMAKE_SOURCE_DIR}/python/bindings.h) 4set(typesystem_file ${CMAKE_SOURCE_DIR}/python/bindings.xml) 5 6set(generated_sources 7 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_module_wrapper.cpp 8 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_wrapper.cpp 9 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_converter_wrapper.cpp 10 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_unit_wrapper.cpp 11 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_unitcategory_wrapper.cpp 12 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_updatejob_wrapper.cpp 13 ${CMAKE_CURRENT_BINARY_DIR}/KUnitConversion/kunitconversion_value_wrapper.cpp) 14 15set(qt_libs Qt6::Core)The first line just defines the name of the Python library we’ll build later. Then we set the header file that includes all the necessary headers of the library. We’ll see that file later. The generated sources list is a bit more complicated, as you need to guess the names of the files generated by Shiboken. Fortunately, you can probably guess the pattern from the example above: the first two files are always the same (the name of the library + _module_wrapper or _wrapper) and the rest is the list of classes defined in your XML file (more about it later). The qt_libs variable just contains a list of the Qt modules that our library requires. You should list all of them, even if one depends on another, because otherwise Shiboken won’t be able to find the include directories.
17ecm_generate_python_bindings( 18 PACKAGE_NAME ${bindings_library} 19 VERSION ${KF_VERSION} 20 WRAPPED_HEADER ${wrapped_header} 21 TYPESYSTEM ${typesystem_file} 22 GENERATED_SOURCES ${generated_sources} 23 INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/${KDE_INSTALL_INCLUDEDIR_KF}/KUnitConversion 24 QT_LIBS ${qt_libs} 25 QT_VERSION ${REQUIRED_QT_VERSION} 26 HOMEPAGE_URL "https://invent.kde.org/frameworks/kunitconversion" 27 ISSUES_URL "https://bugs.kde.org/describecomponents.cgi?product=frameworks-kunitconversion" 28)This is the magic part. The ecm_generate_python_bindings function takes care of running Shiboken with all the required arguments, building the Python library and a wheel file to publish it on the Python Package Index (pypi.org). It has the following arguments:
- PACKAGE_NAME: Name of the Python library.
- VERSION: Version of the resulting library.
- WRAPPED_HEADER: The header file we talked about above.
- TYPESYSTEM: XML file with the type system information.
- GENERATED_SOURCES: The list of files that Shiboken will generate.
- INCLUDE_DIRS: A list with additional include directories that are required for the library. It’s typically the location where the header files included in the WRAPPER_HEADER are.
- QT_LIBS: The list of Qt libraries as explained above.
- QT_VERSION: The minimum required Qt version.
- HOMEPAGE_URL: A URL to the homepage of the project.
- ISSUES_URL: A URL where users can report bugs.
The last part links the C++ library with the Python bindings and installs it. Now let’s take a look at the header file:
1#pragma once 2 3// Make "signals:", "slots:" visible as access specifiers 4#define QT_ANNOTATE_ACCESS_SPECIFIER(a) __attribute__((annotate(#a))) 5 6#include <KUnitConversion/Converter> 7#include <KUnitConversion/Unit> 8#include <KUnitConversion/UnitCategory> 9#include <KUnitConversion/Value>Nothing exciting there, just the list of includes (and some Qt thing that I don’t understand).
The last file you need is the typesystem definition, where you tell Shiboken which things (classes, structs, enums, namespaces…) you want to include in your bindings and how it should interpret them. You can delete or rename functions, change the return type, modify the input parameters and many other things. You may want to take a look at the documentation because the list of posible options is very large.
1<?xml version="1.0"?> 2<typesystem package="KUnitConversion"> 3 <load-typesystem name="typesystem_core.xml" generate="no" /> 4 5 <namespace-type name="KUnitConversion"> 6 <enum-type name="CategoryId" /> 7 <object-type name="Converter" /> 8 <object-type name="Unit" /> 9 <object-type name="UnitCategory" /> 10 <enum-type name="UnitId" /> 11 <object-type name="UpdateJob" /> 12 <object-type name="Value" /> 13 </namespace-type> 14</typesystem>You need to load the typesystems of the Qt libraries that you are using so Shiboken can understand what your code is referring to. They come included with PySide.
That’s all you need to generate the Python bindings for your library. The last step is building the project as you usually do.
Joerg Jaspert: Electric Car, Vacation trip
A while ago I got my hands on an electric car - after not having owned a car for most of my life (there really is not much need here). It wasn’t planned nor a goal of mine, but it kind of “came out of talks with my boss”, so now it’s there.
Due to some special rules in the german tax system it turns out really cheap for me - it comes from the company, which allows personal use. So I have to pay taxes on the value of it plus whichever amount of kilometers I have to drive to work. And the latter is what is good for me - I have homeoffice in my contract, so no drive to work, except maybe once a year for something. So no regular trip to calculate, only if I ever really have to do a trip to the office.
And it being an electric car, running costs are also cheap. Way below the outdated tech that needs gas to run, is annoyingly loud and stinks.
The carIn the past I used either car sharing or renting a car when I needed one, depending on what I actually needed. Last times renting I already tried electric variants, so I could compare this with.
What I have now is a “Citroen e-Berlingo XL” from 2023 (so not the latest change from 2024), which is on the huge size for space, but small for battery. It has 7 seats (though I have the last 2 currently taken out, no daily need) and more storage space than I need even on a vacation trip.
The engine (or well, it’s battery) is on the small side - a capacity of 50 kWh means it only has 278km reach according to WLTP. That actually is a good bit less - as usual, those numbers are lying for the producer. Turns out that on highways in a more realistic mode than WLTP (read: real driving) it’s somewhat around 120km before one wants a charger again. But, looking around, at least in Germany that is not a big problem, there are more than enough chargers available.
DrivingActually driving experience is good. It sure is a huge car (4.7m long, 1.85m high/wide) and feels more like driving a (small) bus, but it is easy to handle. Maximum speed is limited (or the small battery would suck even more) to 135km/h, but that is more than enough. Even on german highways. Did my vacation trip with cruise control set to 115km/h and very few times only went above that manually. Real relaxed driving that was.
Vacation tripSo we had a vacation just recently, and instead of renting a car for the trip we, of course, wanted to take the e-Berlingo. Distance was about double what the car can (realistically!) do, so one charging stop in the middle somewhere was a must. Not having had to charge on highways yet - and entirely new with this car - that made for a bit of nervousness, but it all turned out really good. There are really nice tools like ABRP to plan your trip including charging, which can take live data of availability of charging points into the planning.
And it turned out nice - we reached our planned charging point and found a long queue of cars waiting. But turns out it was all those poor folks that need actual gasoline for their outdated combustion engines. The charging points for EV cars still had enough free space, so we could bypass the queue and directly start charging. We also did not need to repark the car after just a few minutes, we could directly start our break.
With a charging time of approx. 30 minutes using the fast charger, such a break is long enough to get enough energy for the next part of the trip and short enough to not be annoying.
Charging pricesAt home it depends. If one has some photovoltaic system to get power, charging is basically free. If not it depends on whichever contract one has, costs will be somewhat between 0 and ~30cent per kWh. Not much, and way below gasoline costs.
Outside, using a fast charger, prices vary depending on where you charge - and with what charging card. Prices between 40 and 70cent / kWh, and the same charging point can vary, just from the card one uses. That is a thing that the EU could actually go and better regulate, similar to the phone regulations it took. Still, the costs are still way below gasoline.
Charging cardsThere is a huge amount of different providers available, and all do their own things in pricing and how one can use them. They do have standards (say, the plugs are standardized, by now the way to start charging also), and that enables roaming (use a charging card of one provider at a charging point of another), but other than that, it seems to be random.
That is - if you use card A on a charging point of Provider B you may pay 0.49cents, if you use card C on the same point, it may charge you 0.79cents. And card D isn’t taken at all. Some (the newer ones) you can pay directly by credit card, many you can’t. Some may allow paypal or Google/Apple Pay. So in the end you need more than just one charging card - I collected 8 free ones by now - just to be sure you can find a combination that isn’t hugely overpriced.
Drupal blog: Drupal CMS: the official name for Drupal Starshot
This blog has been re-posted and edited with permission from Dries Buytaert's blog.
We're excited to announce that "Drupal CMS" will be the official name for the product developed by the Drupal Starshot Initiative.
The name "Drupal CMS" was chosen after user testing with both newcomers and experienced users. This name consistently scored highest across all tested groups, including marketers unfamiliar with Drupal.
Participants appreciated the clarity it brings:
Having the words CMS in the name will make it clear what the product is. People would know that Drupal was a content management system by the nature of its name, rather than having to ask what Drupal is.
I'm a designer familiar with the industry, so the term CMS or content management system is the term or phrase that describes this product most accurately in my opinion. I think it is important to have CMS in the title.
The name "Drupal Starshot" will remain an internal code name until the first release of Drupal CMS, after which it will most likely be retired.