Skip to content
Snippets Groups Projects
Unverified Commit 35651360 authored by Pawit Pornkitprasan's avatar Pawit Pornkitprasan Committed by GitHub
Browse files

Fix {0} being shown when locale is "pt" (#17875)

This is a combination of 2 issues:
 1) pt got renamed to pt_BR in x.39.x but the old
    "pt" value may still be stored in the database
 2) when making a release, an unclean build
    directory may be used containing old "pt"
    resource which gets leaked into the release build

1) is fixed by adding a function to treat "pt" as "pt_BR"
to support users who were on "pt" since pre-x.39.
(This is done by finding the closest fallback locale)

2) is fixed by emptying the folder before generating locales
so any old locales are deleted.

Fixes #16690
parent 594c4b07
No related branches found
No related tags found
No related merge requests found
......@@ -25,6 +25,9 @@
(u/announce "Artifacts for locale %s created successfully." (pr-str locale))))
(defn- create-artifacts-for-all-locales! []
;; Empty directory in case some locales were removed
(u/delete-file-if-exists! backend/target-directory)
(u/delete-file-if-exists! frontend/target-directory)
(doseq [locale (i18n/locales)]
(create-artifacts-for-locale! locale)))
......
......@@ -43,7 +43,7 @@
(defn- i18n-map [locale]
(->i18n-map (i18n/po-contents locale)))
(def ^:private target-directory
(def target-directory
(u/filename u/project-root-directory "resources" "frontend_client" "app" "locales"))
(defn- target-filename [locale]
......
......@@ -44,8 +44,8 @@
(when-not (= locale-name "en")
(try
(slurp (or (io/resource (localization-json-file-name locale-name))
(when-let [parent-locale (i18n/parent-locale locale-name)]
(io/resource (localization-json-file-name (str parent-locale))))
(when-let [fallback-locale (i18n/fallback-locale locale-name)]
(io/resource (localization-json-file-name (str fallback-locale))))
;; don't try to i18n the Exception message below, we have no locale to translate it to!
(throw (FileNotFoundException. (format "Locale '%s' not found." locale-name)))))
(catch Throwable e
......
......@@ -14,9 +14,9 @@
(p/import-vars
[impl
available-locale?
fallback-locale
locale
normalized-locale-string
parent-locale
translate])
(def ^:dynamic *user-locale*
......
......@@ -57,14 +57,45 @@
(when-let [locale (locale locale-or-name)]
(LocaleUtils/isAvailableLocale locale))))
(defn parent-locale
"For langugage + country Locales, returns the language-only Locale. Otherwise returns `nil`.
(defn- available-locale-names*
[]
(log/info "Reading available locales from locales.clj...")
(some-> (io/resource "locales.clj") slurp edn/read-string :locales (->> (apply sorted-set))))
(def ^{:arglists '([])} available-locale-names
"Return sorted set of available locales, as Strings.
(parent-locale \"en/US\") ; -> #object[java.util.Locale 0x79301688 \"en\"]"
(available-locale-names) ; -> #{\"en\" \"nl\" \"pt-BR\" \"zh\"}"
(let [locales (delay (available-locale-names*))]
(fn [] @locales)))
(defn- find-fallback-locale*
^Locale [^Locale a-locale]
(some (fn [locale-name]
(let [try-locale (locale locale-name)]
;; The language-only Locale is tried first by virtue of the
;; list being sorted.
(when (and (= (.getLanguage try-locale) (.getLanguage a-locale))
(not (= try-locale a-locale)))
try-locale)))
(available-locale-names)))
(def ^:private ^{:arglists '([a-locale])} find-fallback-locale
(memoize find-fallback-locale*))
(defn fallback-locale
"Find a translated fallback Locale in the following order:
1) If it is a language + country Locale, try the language-only Locale
2) If the language-only Locale isn't translated or the input is a language-only Locale,
find the first language + country Locale we have a translation for.
Return `nil` if no fallback Locale can be found or the input is invalid.
(fallback-locale \"en_US\") ; -> #locale\"en\"
(fallback-locale \"pt\") ; -> #locale\"pt_BR\"
(fallback-locale \"pt_PT\") ; -> #locale\"pt_BR\""
^Locale [locale-or-name]
(when-let [a-locale (locale locale-or-name)]
(when (seq (.getCountry a-locale))
(locale (.getLanguage a-locale)))))
(find-fallback-locale a-locale)))
(defn- locale-edn-resource
"The resource URL for the edn file containing translations for `locale-or-name`. These files are built by the
......@@ -106,9 +137,9 @@
(or (when (= (.getLanguage a-locale) "en")
format-string)
(translated-format-string* a-locale format-string)
(when-let [parent-locale (parent-locale a-locale)]
(log/tracef "No translated string found, trying parent locale %s" (pr-str parent-locale))
(translated-format-string* parent-locale format-string))
(when-let [fallback-locale (fallback-locale a-locale)]
(log/tracef "No translated string found, trying fallback locale %s" (pr-str fallback-locale))
(translated-format-string* fallback-locale format-string))
format-string)))
(defn- message-format ^MessageFormat [locale-or-name ^String format-string]
......@@ -144,18 +175,6 @@
(log/errorf e "Invalid format string %s" (pr-str format-string))
format-string))))))
(defn- available-locale-names*
[]
(log/info "Reading available locales from locales.clj...")
(some-> (io/resource "locales.clj") slurp edn/read-string :locales set))
(def ^{:arglists '([])} available-locale-names
"Return set of available locales, as Strings.
(available-locale-names) ; -> #{\"nl\" \"pt\" \"en\" \"zh\"}"
(let [locales (delay (available-locale-names*))]
(fn [] @locales)))
;; We can't fetch the system locale until the application DB has been initiailized. Once that's done, we don't need to
;; do the check anymore -- swapping out the getter fn with the simpler one speeds things up substantially
(def ^:private site-locale-from-setting-fn
......
......@@ -55,18 +55,21 @@
(is (= expected
(impl/available-locale? locale))))))
(deftest parent-locale-test
(doseq [[locale expected] {nil nil
:es nil
"es" nil
(deftest fallback-locale-test
(doseq [[locale expected] {nil nil
:es nil
"es" nil
(Locale/forLanguageTag "es") nil
"es-MX" (Locale/forLanguageTag "es")
"es_MX" (Locale/forLanguageTag "es")
:es/MX (Locale/forLanguageTag "es")
(Locale/forLanguageTag "es-MX") (Locale/forLanguageTag "es")}]
"es-MX" (Locale/forLanguageTag "es")
"es_MX" (Locale/forLanguageTag "es")
:es/MX (Locale/forLanguageTag "es")
(Locale/forLanguageTag "es-MX") (Locale/forLanguageTag "es")
;; 0.39 changed pt to pt_BR (metabase#15630)
"pt" (Locale/forLanguageTag "pt-BR")
"pt-PT" (Locale/forLanguageTag "pt-BR")}]
(testing locale
(is (= expected
(impl/parent-locale locale))))))
(impl/fallback-locale locale))))))
(deftest graceful-fallback-test
(testing "If a resource bundle doesn't exist, we should gracefully fall back to English"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment