This repository contains the i18nGen command line tool that takes language/localization yaml files as input and automatically generates Swift and Kotlin code containing the localized strings.
This tool is compatible with lyaml
files generated by Transifex, and it was originally developed for HubSpot's mobile apps.
Watch the presentation on YouTube.
i18nGen requires Swift 5 and it was tested on macOS 10.14 and Ubuntu 18.04
- Clone this repository:
$ git clone https://github.com/fabio914/mobile-i18n.git
- Go to the mobile-i18n-generator folder:
$ cd mobile-i18n
- Run the install script:
$ ./install.sh
or
$ ./installLinux.sh
$ i18nGen <main language YAML file> [additional language YAML files ...] [output options] [warning options]
Examples (Swift):
$ i18nGen en.lyaml de.lyaml es.lyaml fr.lyaml ja.lyaml pt-br.lyaml -swift
Outputs a Swift dictionary, without warnings:
$ i18nGen en.lyaml de.lyaml es.lyaml fr.lyaml ja.lyaml pt-br.lyaml -swift-dictionary -w
All warnings:
$ i18nGen en.lyaml de.lyaml es.lyaml fr.lyaml ja.lyaml pt-br.lyaml -swift -Wall
Examples (Kotlin):
$ i18nGen en.lyaml de.lyaml es.lyaml fr.lyaml ja.lyaml pt-br.lyaml -kotlin com.organization.localization
Outputs Kotlin code without static strings:
$ i18nGen en.lyaml de.lyaml es.lyaml fr.lyaml ja.lyaml pt-br.lyaml -kotlin-filtered com.organization.localization
All warnings:
$ i18nGen en.lyaml de.lyaml es.lyaml fr.lyaml ja.lyaml pt-br.lyaml -kotlin com.organization.localization -Wall
A Localization.swift
(or Localization.kt
) file will be generated if i18nGen succeeds.
- Add an
en.lyaml
file to your project/target (DO NOT add this file, or any other.lyaml
file, to the Copy Bundle Resources phase):
en:
hello:
title: "Hello"
message: "Hello {{ name }}!"
done: "Done"
- Add a new Build Rule to your XCode project/target:
cd ${DERIVED_FILE_DIR}
i18nGen ${INPUT_FILE_PATH} `find ${INPUT_FILE_DIR} -name "*.lyaml" | grep -v en.lyaml | tr '\n' ' '` -swift
- Add the
en.lyaml
file to the Compile Sources phase:
- Add additional language files (DO NOT add these
.lyaml
files to the Copy Bundle Resources or Compile Sources phase):
es:
hello:
title: "Hola"
message: "¡Hola {{ name }}!"
done: "Hecho"
pt-br:
hello:
title: "Olá"
message: "Olá {{ name }}!"
done: "Feito"
Remember to keep these .lyaml
files all on the same directory in your target/project.
XCode will only track changes to the en.lyaml
file. Remember to clean the project (including your project's derived data) by pressing ⌥⇧⌘K when modifying any of the other .lyaml
files or updating the i18nGen tool!
-
Build the project.
-
Your strings will be defined under
LocalizedStrings
and you can access them via thelocalizedStrings
instance:
let namespace = localizedStrings.hello
let alert = UIAlertController(title: namespace.title, message: namespace.message(name: "John"), preferredStyle: .alert)
alert.addAction(UIAlertAction(title: namespace.done, style: .default, handler: { _ in }))
present(alert, animated: true, completion: nil)
- Result:
Usage with XCodeGen (iOS)
- Add an
en.lyaml
file to your target:
en:
hello:
title: "Hello"
message: "Hello {{ name }}!"
done: "Done"
- Add your
en.lyaml
file to yourproject.yml
's target sources:
sources:
# ...
- path: "path/to/folder/en.lyaml"
buildPhase: sources
createIntermediateGroups: true
- Add a new Build Rule to your
project.yml
's target:
buildRules:
# ...
- name: Localize
filePattern: "*/en.lyaml"
script: |
cd ${DERIVED_FILE_DIR}
i18nGen ${INPUT_FILE_PATH} `find ${INPUT_FILE_DIR} -name "*.lyaml" | grep -v en.lyaml | tr '\n' ' '` -swift
outputFiles:
- $(DERIVED_FILE_DIR)/Localization.swift
- Add additional language files (inside the same folder as your
en.lyaml
):
es:
hello:
title: "Hola"
message: "¡Hola {{ name }}!"
done: "Hecho"
pt-br:
hello:
title: "Olá"
message: "Olá {{ name }}!"
done: "Feito"
- Add the extra language files to your
project.yml
(optional):
sources:
# ...
- path: "path/to/folder"
buildPhase: none
createIntermediateGroups: true
excludes:
- "en.lyaml"
- Regenerate your XCode project:
$ xcodegen generate
-
Build your target.
-
Your strings will be defined under
LocalizedStrings
and you can access them via thelocalizedStrings
instance:
let namespace = localizedStrings.hello
let alert = UIAlertController(title: namespace.title, message: namespace.message(name: "John"), preferredStyle: .alert)
alert.addAction(UIAlertAction(title: namespace.done, style: .default, handler: { _ in }))
present(alert, animated: true, completion: nil)
- Result:
PS: Our gradle plugin needs to be updated to version 2.0.
- Add these rules to your root-level
build.gradle
file:
apply plugin: 'com.i18n.community.localization'
buildscript {
// ...
repositories {
// ...
jcenter()
}
dependencies {
// ...
classpath "com.i18n.community.localization:GradlePlugin:1.0.+"
}
}
-
Create a
lang
directory inside your module's root; -
Create an
en.lyaml
file inside thatlang
directory:
en:
hello:
title: "Hello"
message: "Hello {{ name }}!"
done: "Done"
- Create additional language files
es:
hello:
title: "Hola"
message: "¡Hola {{ name }}!"
done: "Hecho"
pt-br:
hello:
title: "Olá"
message: "Olá {{ name }}!"
done: "Feito"
-
Build the project.
-
Your strings will be defined under
LocalizedStrings
:
val namespace = LocalizedStrings.hello
AlertDialog.Builder(this)
.setTitle(namespace.title)
.setMessage(namespace.message(name = "John"))
.setPositiveButton(namespace.done) { _, _ -> }
.create()
.show()
- Result: