diff --git a/src/modules/locale/LocaleConfiguration.cpp b/src/modules/locale/LocaleConfiguration.cpp
index f1810fb83..055907228 100644
--- a/src/modules/locale/LocaleConfiguration.cpp
+++ b/src/modules/locale/LocaleConfiguration.cpp
@@ -37,7 +37,7 @@ LocaleConfiguration::LocaleConfiguration( const QString& localeName, const QStri
     lc_numeric = lc_time = lc_monetary = lc_paper = lc_name = lc_address = lc_telephone = lc_measurement
         = lc_identification = formatsName;
 
-    (void)setLanguage( localeName );
+    setLanguage( localeName );
 }
 
 
@@ -83,7 +83,7 @@ LocaleConfiguration::fromLanguageAndLocation( const QString& languageLocale,
     if ( language == "pt" || language == "zh" )
     {
         QString proposedLocale = QString( "%1_%2" ).arg( language ).arg( countryCode );
-        foreach ( QString line, linesForLanguage )
+        for ( const QString& line : linesForLanguage )
         {
             if ( line.contains( proposedLocale ) )
             {
diff --git a/src/modules/locale/LocaleConfiguration.h b/src/modules/locale/LocaleConfiguration.h
index 4f4fc6b21..2e02bc02a 100644
--- a/src/modules/locale/LocaleConfiguration.h
+++ b/src/modules/locale/LocaleConfiguration.h
@@ -26,36 +26,53 @@
 
 class LocaleConfiguration
 {
-public:
-    /// @brief Create an empty locale, with nothing set
-    explicit LocaleConfiguration();
-    /// @brief Create a locale with everything set to the given @p localeName
+public:  // TODO: private (but need to be public for tests)
+    /** @brief Create a locale with everything set to the given @p localeName
+     *
+     * Consumers should use fromLanguageAndLocation() instead.
+     */
     explicit LocaleConfiguration( const QString& localeName /* "en_US.UTF-8" */ )
         : LocaleConfiguration( localeName, localeName )
     {
     }
-    /// @brief Create a locale with language and formats separate
+    /** @brief Create a locale with language and formats separate
+     *
+     * Consumers should use fromLanguageAndLocation() instead.
+     */
     explicit LocaleConfiguration( const QString& localeName, const QString& formatsName );
 
+    /// @brief Create an empty locale, with nothing set
+    explicit LocaleConfiguration();
+
+    /** @brief Create a "sensible" locale configuration for @p language and @p countryCode
+     *
+     * This method applies some heuristics to pick a good locale (from the list
+     * @p availableLocales), along with a good language (for instance, in
+     * large countries with many languages, picking a generally used one).
+     */
     static LocaleConfiguration
     fromLanguageAndLocation( const QString& language, const QStringList& availableLocales, const QString& countryCode );
 
+    /// Is this an empty (default-constructed and not modified) configuration?
     bool isEmpty() const;
 
-    /** @brief sets lang and the BCP47 representation
+    /** @brief sets language to @p localeName
      *
-     * Note that the documentation how this works is in packages.conf
+     * The language may be regionalized, e.g. "nl_BE". Both the language
+     * (with region) and BCP47 representation (without region, lowercase)
+     * are updated. The BCP47 representation is used by the packages module.
+     * See also `packages.conf` for a discussion of how this is used.
      */
     void setLanguage( const QString& localeName );
+    /// Current language (including region)
     QString language() const { return m_lang; }
-
-    // Note that the documentation how this works is in packages.conf
+    /// Current language (lowercase, BCP47 format, no region)
     QString toBcp47() const { return m_languageLocaleBcp47; }
 
     QMap< QString, QString > toMap() const;
 
     // These become all uppercase in locale.conf, but we keep them lowercase here to
-    // avoid confusion with locale.h.
+    // avoid confusion with <locale.h>, which defines (e.g.) LC_NUMERIC macro.
     QString lc_numeric, lc_time, lc_monetary, lc_paper, lc_name, lc_address, lc_telephone, lc_measurement,
         lc_identification;