-
Notifications
You must be signed in to change notification settings - Fork 3
Example project integration
intlc deliberately takes a non-monolithic approach to the compilation of translation messages. We intend to improve ease of use and integration (#160), however for the time being you'll need to do a little bit of extra bootstrapping yourself.
You'll need a shell script or similar which can find all the translation files in your project and feed them into intlc. For this reason we recommend a consistent, distinct approach to file naming, such as lang/<locale>.translations.json
.
This shell script is very similar to what we use at Unsplash on the Web team. It compiles all our translations across all locales to sibling files; for example ja-JP.translations.json
will be compiled to ja-JP.tsx
. Everything in our repo compiles in around 200ms.
#!/usr/bin/env bash
dirs=$(fd -t d lang)
compile_dir() {
dir="$1"
files=$(find "$dir" -name "*.translations.json" -type f)
if [ -n "$files" ]; then
for file in $files; do
filename=$(basename "$file")
locale="${filename%%.*}"
intlc compile "$file" -l "$locale" > "$dir/$locale.tsx"
done
cp ./templates/lang-index.ts "$dir/index.ts"
fi
}
# Extracted into a function so that we can fork for each directory, improving performance.
for dir in $dirs; do compile_dir "$dir" & done
wait
(The use of fd over find at the top is optional.)
In the cp
above we copy an index to every lang
directory. This is what you'll import from your code. This file needs to re-export from each compiled locale. It will very roughly look something like this:
import * as enUS from './en-US'
import * as jaJP from './ja-JP'
export type Translations = typeof enUS
export const getTranslations = (loc: 'en-US' | 'ja-JP'): Translations => {
switch (loc) {
case 'en-US': return enUS
case 'ja-JP': return jaJP
}
}
The index is where type safety can be enforced, as with the use of Translations
on the return type above. Your master translations, for example English, can be used to ensure compatible type signatures across locales.
In this way type safety across locales isn't a concern of intlc and is instead offloaded to tsc. TypeScript's subtyping makes this particularly straightforward, as messages needn't necessarily use the same interpolations across locales, they need merely be compatible i.e. { name: string }
and { age: number }
are compatible insofar as they can be intersected, but { name: string }
and { name: number }
are not because you can't provide a string & number
.
This is something we're working on now with React suspense and SSR in mind. We'll update this page when we've got something we're ready to share.
In theory, because you're just working with output .ts
files, this can already be implemented in any way you'd please, for example making the above imports dynamic and returning a promise.
You can integrate watching in any number of ways. We currently use watchexec:
watchexec -f '*.translations.json' -n -- sh -c './compile.sh && echo OK'