Skip to content

Commit

Permalink
Port code for building i18n resources to Clojure build scripts (metab…
Browse files Browse the repository at this point in the history
…ase#15189)

* Port code for building i18n resources to Clojure build scripts; remove dep on gettext

* Use Metabase classloader

* Test fixes 🔧

* Bump adoptopenjdk version

* Delete gettext dependency from Dockerfile

* Update developers-guide.md

* Address PR feedback

* Fix frontend singular msgstr format

Co-authored-by: Luis Paolini <[email protected]>
  • Loading branch information
camsaul and paoliniluis authored Mar 17, 2021
1 parent 80f984c commit aa211a5
Show file tree
Hide file tree
Showing 27 changed files with 408 additions and 232 deletions.
5 changes: 5 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,11 @@ jobs:
command: |
cd /home/circleci/metabase/metabase/bin/build-drivers && clojure -M:test
no_output_timeout: 15m
- run:
name: Run i18n script tests
command: |
cd /home/circleci/metabase/metabase/bin/i18n && clojure -M:test
no_output_timeout: 15m
- run:
name: Run build-mb build script tests
command: |
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/i18n.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ jobs:

- run: sudo apt install gettext

- name: Install Clojure CLI
run: |
curl -O https://download.clojure.org/install/linux-install-1.10.1.708.sh &&
sudo bash ./linux-install-1.10.1.708.sh
- run: ./bin/i18n/update-translation-template
name: Check i18n tags/make sure template can be built
- run: ./bin/i18n/build-translation-resources
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/uberjar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ jobs:
uses: actions/setup-java@v1
with:
java-version: 8
- name: Install gettext
run: sudo apt install gettext
- name: Install Clojure CLI
run: |
curl -O https://download.clojure.org/install/linux-install-1.10.1.708.sh &&
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
/resources/frontend_client/embed.html
/resources/frontend_client/index.html
/resources/frontend_client/public.html
/resources/i18n/*.edn
/resources/namespaces.edn
/resources/sample-dataset.db.trace.db
/resources/version.properties
Expand Down
9 changes: 3 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ RUN yarn install --frozen-lockfile
# STAGE 1.2: builder backend
###################

# Build currently doesn't work on > Java 11 (i18n utils are busted) so build on 8 until we fix this
FROM adoptopenjdk/openjdk8:alpine as backend
FROM adoptopenjdk/openjdk11:alpine as backend

ARG MB_EDITION=oss

Expand All @@ -45,8 +44,7 @@ RUN lein deps
# STAGE 1.3: main builder
###################

# Build currently doesn't work on > Java 11 (i18n utils are busted) so build on 8 until we fix this
FROM adoptopenjdk/openjdk8:alpine as builder
FROM adoptopenjdk/openjdk11:alpine as builder

ARG MB_EDITION=oss

Expand All @@ -58,10 +56,9 @@ ENV FC_LANG en-US LC_CTYPE en_US.UTF-8
# curl: needed by script that installs Clojure CLI
# git: ./bin/version
# yarn: frontend building
# gettext: translations
# java-cacerts: installs updated cacerts to /etc/ssl/certs/java/cacerts

RUN apk add --no-cache coreutils bash yarn git curl gettext java-cacerts
RUN apk add --no-cache coreutils bash yarn git curl java-cacerts

# lein: backend dependencies and building
RUN curl https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein -o /usr/local/bin/lein && \
Expand Down
1 change: 1 addition & 0 deletions bin/build-mb/deps.edn
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
:deps
{common/common {:local/root "../common"}
build-drivers/build-drivers {:local/root "../build-drivers"}
i18n/i18n {:local/root "../i18n"}
org.flatland/ordered {:mvn/version "1.5.7"}}

:aliases
Expand Down
13 changes: 3 additions & 10 deletions bin/build-mb/src/build.clj
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,8 @@
[clojure.string :as str]
[environ.core :as env]
[flatland.ordered.map :as ordered-map]
[metabuild-common.core :as u]
[metabuild-common.java :as java]))

(defn- build-translation-resources!
[]
(u/step "Build translation resources"
(java/check-java-8)
(u/sh {:dir u/project-root-directory} "./bin/i18n/build-translation-resources")
(u/announce "Translation resources built successfully.")))
[i18n.create-artifacts :as i18n]
[metabuild-common.core :as u]))

(defn- edition-from-env-var []
(case (env/env :mb-edition)
Expand Down Expand Up @@ -66,7 +59,7 @@
:version (fn [{:keys [version]}]
(version-info/generate-version-info-file! version))
:translations (fn [_]
(build-translation-resources!))
(i18n/create-all-artifacts!))
:frontend (fn [{:keys [edition]}]
(build-frontend! edition))
:drivers (fn [{:keys [edition]}]
Expand Down
18 changes: 0 additions & 18 deletions bin/common/src/metabuild_common/java.clj

This file was deleted.

72 changes: 0 additions & 72 deletions bin/i18n/build-translation-frontend-resource

This file was deleted.

52 changes: 6 additions & 46 deletions bin/i18n/build-translation-resources
Original file line number Diff line number Diff line change
@@ -1,49 +1,9 @@
#!/bin/sh
#! /usr/bin/env bash

set -eu
set -euo pipefail

# gettext installed via homebrew is "keg-only", add it to the PATH
if [ -d "/usr/local/opt/gettext/bin" ]; then
export PATH="/usr/local/opt/gettext/bin:$PATH"
fi
source "./bin/check-clojure-cli.sh"
check_clojure_cli

POT_NAME="locales/metabase.pot"
LOCALES=$(find locales -type f -name "*.po" -exec basename {} .po \;)

if [ -z "$LOCALES" ]; then
LOCALES_QUOTED=""
else
LOCALES_QUOTED=" $(echo "$LOCALES" | awk '{ printf "\"%s\" ", $0 }')"
fi

FRONTEND_LANG_DIR="resources/frontend_client/app/locales"

# backend
# NOTE: include "en" even though we don't have a .po file for it because it's the default?
cat << EOF > "resources/locales.clj"
{
:locales #{"en"$LOCALES_QUOTED}
:packages ["metabase"]
:bundle "metabase.Messages"
}
EOF

mkdir -p "$FRONTEND_LANG_DIR"

for LOCALE in $LOCALES; do
LOCALE_FILE="locales/$LOCALE.po"
LOCALE_WITH_UNDERSCORE=$(echo "$LOCALE" | tr '-' '_')
# frontend
# NOTE: just copy these for now, but eventially precompile from .po to .json
./bin/i18n/build-translation-frontend-resource \
"$LOCALE_FILE" \
"$FRONTEND_LANG_DIR/$LOCALE_WITH_UNDERSCORE.json"

# backend
msgfmt \
--java2 \
-d "resources" \
-r "metabase.Messages" \
-l "$LOCALE_WITH_UNDERSCORE" \
"$LOCALE_FILE"
done
cd bin/i18n
clojure -M -m i18n.create-artifacts $@
13 changes: 13 additions & 0 deletions bin/i18n/deps.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{:paths ["src"]

:deps
{common/common {:local/root "../common"}
cheshire/cheshire {:mvn/version "5.8.1"}
clj-http/clj-http {:mvn/version "3.9.1"}
org.fedorahosted.tennera/jgettext {:mvn/version "0.15.1"}}

:aliases
{:test {:extra-paths ["test"]
:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner.git"
:sha "209b64504cb3bd3b99ecfec7937b358a879f55c1"}}
:main-opts ["-m" "cognitect.test-runner"]}}}
59 changes: 59 additions & 0 deletions bin/i18n/src/i18n/common.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
(ns i18n.common
(:require [clojure.java.io :as io]
[clojure.string :as str]
[metabuild-common.core :as u])
(:import [org.fedorahosted.tennera.jgettext Catalog HeaderFields Message PoParser]))

(defn locales
"Set of all locales for which we have i18n bundles.
(locales) ; -> #{\"nl\" \"pt\" \"zh\" \"tr\" \"it\" \"fa\" ...}"
[]
(set (for [^java.io.File file (.listFiles (io/file (u/filename u/project-root-directory "locales")))
:let [file-name (.getName file)]
:when (str/ends-with? file-name ".po")]
(str/replace file-name #"\.po$" ""))))

(defn locale-source-po-filename [locale]
(u/filename u/project-root-directory "locales" (format "%s.po" locale)))

;; see https://github.com/zanata/jgettext/tree/master/src/main/java/org/fedorahosted/tennera/jgettext

(defn- catalog ^Catalog [locale]
(let [parser (PoParser.)]
(.parseCatalog parser (io/file (locale-source-po-filename "es")))))

(defn po-headers [locale]
(when-let [^Message message (.locateHeader (catalog locale))]
(let [header-fields (HeaderFields/wrap (.getMsgstr message))]
(into {} (for [^String k (.getKeys header-fields)]
[k (.getValue header-fields k)])))))

(defn po-messages-seq [locale]
(for [^Message message (iterator-seq (.iterator (catalog locale)))
;; remove any empty translations
:when (not (str/blank? (.getMsgid message)))]
{:id (.getMsgid message)
:id-plural (.getMsgidPlural message)
:str (.getMsgstr message)
:str-plural (seq (remove str/blank? (.getMsgstrPlural message)))
:fuzzy? (.isFuzzy message)
:plural? (.isPlural message)
:source-references (seq (remove str/blank? (.getSourceReferences message)))
:comment (.getMsgctxt message)}))

(defn po-contents [locale]
{:headers (po-headers locale)
:messages (po-messages-seq locale)})

(defn print-message-count-xform [rf]
(let [num-messages (volatile! 0)]
(fn
([]
(rf))
([result]
(u/announce "Wrote %d messages." @num-messages)
(rf result))
([result message]
(vswap! num-messages inc)
(rf result message)))))
38 changes: 38 additions & 0 deletions bin/i18n/src/i18n/create_artifacts.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
(ns i18n.create-artifacts
(:require [clojure.pprint :as pprint]
[i18n.common :as i18n]
[i18n.create-artifacts.backend :as backend]
[i18n.create-artifacts.frontend :as frontend]
[metabuild-common.core :as u]))

;; TODO -- shouldn't this be `locales.edn`?
(defn- locales-dot-clj []
{:locales (conj (i18n/locales) "en")
:packages ["metabase"]
:bundle "metabase.Messages"})

(defn- generate-locales-dot-clj! []
(u/step "Create resources/locales.clj"
(let [file (u/filename u/project-root-directory "resources" "locales.clj")]
(u/delete-file-if-exists! file)
(spit file (with-out-str (pprint/pprint (locales-dot-clj))))
(u/assert-file-exists file))))

(defn- create-artifacts-for-locale! [locale]
(u/step (format "Create artifacts for locale %s" (pr-str locale))
(frontend/create-artifact-for-locale! locale)
(backend/create-artifact-for-locale! locale)
(u/announce "Artifacts for locale %s created successfully." (pr-str locale))))

(defn- create-artifacts-for-all-locales! []
(doseq [locale (i18n/locales)]
(create-artifacts-for-locale! locale)))

(defn create-all-artifacts! []
(u/step "Create i18n artifacts"
(generate-locales-dot-clj!)
(create-artifacts-for-all-locales!)
(u/announce "Translation resources built successfully.")))

(defn -main []
(create-all-artifacts!))
Loading

0 comments on commit aa211a5

Please sign in to comment.