Localizations Setup (#6)

* Move assets into ElementX folder

* Add first version of localizer script

* Add generated strings & tests & fallback mechanism

* Rename strings file to Localizable

* Rename Assets to Resources

* Calculate preferred languages only when needed, remove share extension check

* Add comments in the localizer script

* Add GH workflow to push issues to the [ElementX board](https://github.com/orgs/vector-im/projects/43)

* Closes #16 - Add license file

* New version of localizer script, handle pluralization

* Move assets into ElementX folder

* Add first version of localizer script

* Add generated strings & tests & fallback mechanism

* Rename strings file to Localizable

* Rename Assets to Resources

* Calculate preferred languages only when needed, remove share extension check

* Add comments in the localizer script

* New version of localizer script, handle pluralization

* Revert login button text

* Add multiple dialect pluralization, fix string formatting

Co-authored-by: manuroe <manu@matrix.org>
Co-authored-by: Stefan Ceriu <stefanc@matrix.org>
This commit is contained in:
ismailgulek
2022-04-26 22:48:17 +03:00
committed by GitHub
parent db86cdb201
commit 4adabaea71
184 changed files with 109472 additions and 14 deletions

View File

@@ -0,0 +1,101 @@
// swiftlint:disable all
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
{% if tables.count > 0 %}
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
import Foundation
// swiftlint:disable superfluous_disable_command file_length implicit_return
// MARK: - Strings
{% macro parametersBlock types %}{% filter removeNewlines:"leading" %}
{% for type in types %}
{% if type == "String" %}
_ p{{forloop.counter}}: Any
{% else %}
_ p{{forloop.counter}}: {{type}}
{% endif %}
{{ ", " if not forloop.last }}
{% endfor %}
{% endfilter %}{% endmacro %}
{% macro argumentsBlock types %}{% filter removeNewlines:"leading" %}
{% for type in types %}
{% if type == "String" %}
String(describing: p{{forloop.counter}})
{% elif type == "UnsafeRawPointer" %}
Int(bitPattern: p{{forloop.counter}})
{% else %}
p{{forloop.counter}}
{% endif %}
{{ ", " if not forloop.last }}
{% endfor %}
{% endfilter %}{% endmacro %}
{% macro recursiveBlock table item %}
{% for string in item.strings %}
{% if not param.noComments %}
{% for line in string.translation|split:"\n" %}
/// {{line}}
{% endfor %}
{% endif %}
{% if string.types %}
{{accessModifier}} static func {{string.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}({% call parametersBlock string.types %}) -> String {
return {{enumName}}.tr("{{table}}", "{{string.key}}", {% call argumentsBlock string.types %})
}
{% elif param.lookupFunction %}
{# custom localization function is mostly used for in-app lang selection, so we want the loc to be recomputed at each call for those (hence the computed var) #}
{{accessModifier}} static var {{string.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}: String { return {{enumName}}.tr("{{table}}", "{{string.key}}") }
{% else %}
{{accessModifier}} static var {{string.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{enumName}}.tr("{{table}}", "{{string.key}}")
{% endif %}
{% endfor %}
{% for child in item.children %}
{{accessModifier}} enum {{child.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
{% filter indent:2 %}{% call recursiveBlock table child %}{% endfilter %}
}
{% endfor %}
{% endmacro %}
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
{% set enumName %}{{param.enumName|default:"L10n"}}{% endset %}
{{accessModifier}} enum {{enumName}} {
{% if tables.count > 1 or param.forceFileNameEnum %}
{% for table in tables %}
{% filter indent:2 %}{% call recursiveBlock table.name table.levels %}{% endfilter %}
{% endfor %}
{% else %}
{% call recursiveBlock tables.first.name tables.first.levels %}
{% endif %}
}
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces
// MARK: - Implementation Details
extension {{enumName}} {
static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String {
let languages = Bundle.preferredLanguages
for language in languages {
let translation = trIn(language, table, key, args)
if translation != key {
return translation
}
}
return key
}
private static func trIn(_ language: String, _ table: String, _ key: String, _ args: CVarArg...) -> String {
guard let bundle = Bundle.lprojBundle(for: language) else {
// no translations for the desired language
return key
}
let format = NSLocalizedString(key, tableName: table, bundle: bundle, comment: "")
return String(format: format, locale: Locale(identifier: language), arguments: args)
}
}
{% else %}
// No string found
{% endif %}

View File

@@ -0,0 +1,75 @@
// swiftlint:disable all
// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen
{% if tables.count > 0 %}
{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %}
import Foundation
// swiftlint:disable superfluous_disable_command file_length implicit_return
// MARK: - Strings
{% macro parametersBlock types %}{% filter removeNewlines:"leading" %}
{% for type in types %}
{% if type == "String" %}
_ p{{forloop.counter}}: Any
{% else %}
_ p{{forloop.counter}}: {{type}}
{% endif %}
{{ ", " if not forloop.last }}
{% endfor %}
{% endfilter %}{% endmacro %}
{% macro argumentsBlock types %}{% filter removeNewlines:"leading" %}
{% for type in types %}
{% if type == "String" %}
String(describing: p{{forloop.counter}})
{% elif type == "UnsafeRawPointer" %}
Int(bitPattern: p{{forloop.counter}})
{% else %}
p{{forloop.counter}}
{% endif %}
{{ ", " if not forloop.last }}
{% endfor %}
{% endfilter %}{% endmacro %}
{% macro recursiveBlock table item %}
{% for string in item.strings %}
{% if not param.noComments %}
{% for line in string.translation|split:"\n" %}
/// {{line}}
{% endfor %}
{% endif %}
{% if string.types %}
{{accessModifier}} static func {{string.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}({% call parametersBlock string.types %}) -> String {
return {{enumName}}.tr("{{table}}", "{{string.key}}", {% call argumentsBlock string.types %})
}
{% elif param.lookupFunction %}
{# custom localization function is mostly used for in-app lang selection, so we want the loc to be recomputed at each call for those (hence the computed var) #}
{{accessModifier}} static var {{string.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}: String { return {{enumName}}.tr("{{table}}", "{{string.key}}") }
{% else %}
{{accessModifier}} static let {{string.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{enumName}}.tr("{{table}}", "{{string.key}}")
{% endif %}
{% endfor %}
{% for child in item.children %}
{{accessModifier}} enum {{child.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} {
{% filter indent:2 %}{% call recursiveBlock table child %}{% endfilter %}
}
{% endfor %}
{% endmacro %}
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
{% set enumName %}{{param.enumName|default:"L10n"}}{% endset %}
extension {{enumName}} {
{% if tables.count > 1 or param.forceFileNameEnum %}
{% for table in tables %}
{% filter indent:2 %}{% call recursiveBlock table.name table.levels %}{% endfilter %}
{% endfor %}
{% else %}
{% call recursiveBlock tables.first.name tables.first.levels %}
{% endif %}
}
// swiftlint:enable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:enable nesting type_body_length type_name vertical_whitespace_opening_braces
{% else %}
// No string found
{% endif %}

View File

@@ -1,8 +1,26 @@
input_dir: ../../ElementX/
output_dir: ../../ElementX/Sources/Generated/
xcassets:
xcassets:
inputs:
- SupportingFiles/Assets.xcassets
- Resources/Assets.xcassets
outputs:
templateName: swift5
output: Assets.swift
strings:
- inputs: Resources/Localizations/en.lproj
filter: Localizable*
outputs:
templatePath: Templates/Strings/structured-swift5-element.stencil
output: Strings.swift
params:
enumName: ElementL10n
lookupFunction: tr # used for the loc to be computed variables
publicAccess: true
- inputs: Resources/Localizations/en.lproj
filter: Untranslated*
outputs:
templatePath: Templates/Strings/structured-swift5-untranslated.stencil
output: Strings+Untranslated.swift
params:
enumName: ElementL10n
publicAccess: true