¡Hola! Si su aplicación admite diferentes idiomas, es probable que haya encontrado problemas relacionados con la localización: errores en las claves de escritura, valores faltantes para los idiomas, la necesidad de reconstruir la aplicación en caso de ediciones de traducción de emergencia. No son los momentos más agradables de desarrollo, ¿verdad?
Este artículo discutirá cómo funciona la localización en Vivid.Money: le diremos qué herramienta de localización eligió, qué problemas encontró y cómo se resolvieron.
Para comprender mejor los detalles del proyecto, puede leer este material y le sugerimos comenzar este artículo sin más preámbulos.
¿Qué método de localización elegiste?
Nuestros requisitos de localización incluyen los siguientes puntos:
Sincronización entre plataformas (iOS, Android, Backend) para una única fuente de verdad;
Comprobar la ortografía correcta de las claves utilizadas durante la compilación para eliminar la posibilidad de cometer un error tipográfico en el nombre de la clave;
No es necesario que los desarrolladores introduzcan localizaciones para diferentes idiomas de forma independiente para que los desarrolladores dediquen más tiempo a hacer lo que deberían: implementar funciones;
Facilidad de interacción con traductores;
La capacidad de cambiar valores clave sin reconstruir la aplicación.
Apple .strings .stringsdict. .strings (“”: “”), . .stringsdict plural plist. , NSLocalizedString. Apple .
, : , , , . XLIFF ( , XML), . , - .
, , , . , , , :
|
Lokalise |
Phrase |
OneSky |
POEditor |
|
+ |
- |
- |
- |
|
+ |
+ |
- |
+ |
plural |
+ |
+ |
+/- |
+ |
SDK |
+ |
+ |
+ |
- |
|
+ |
- |
- |
- |
/ |
+ |
- |
- |
- |
|
+ |
- |
- |
- |
|
+ |
+/- |
- |
- |
|
|
|
https://www.oneskyapp.com/pricing/ |
|
Crowdin, . , - , . Lokalise, , . , , .
lokalise , , , . :
;
Fastlane, ;
API/CLI;
SDK.
, SDK. : , , SDK. , , .
API, Lokalise , . .
, Lokalise SDK, . : . , Lokalise SDK , , , .
(debug/release), .
.strings .stringsdict plutil (property list utility), : .. Ruby:
def self.valid_bundle?(path)
puts 'Validating localization bundle...'
strings = Dir["#{path}/Contents/Resources/*.lproj/*.strings"]
stringsdict = Dir["#{path}/Contents/Resources/*.lproj/*.stringsdict"]
is_valid = true
(strings + stringsdict).each do |path|
stdout, stderr, status = Open3.capture3("plutil -lint #{path}")
unless status.exitstatus == 0
is_valid = false
line = stderr.strip[/on line ([0-9]*)/, 1]
puts "***********************************************".red
puts "Found the invalid string in file at path: #{path}".red
puts "The invalid string: #{File.readlines(path)[line.to_i-1].strip}".red
end
end
puts "***********************************************".red unless is_valid
is_valid
end
Localisation, .
, - . LocalizationFetcher : . , , - . , , Documents, .
, , , Localise.bundle. : Documents .lproj Localizable.strings Localizable.stringsdict Localizable.nocache.strings Localizable.nocache.stringsdict, . “Localizable.nocache” tableName localizedString(forKey:value:table:) , .
, : , , , .
R.swift , .., -, , ( ), -, . .
: Localisation.swift , Localizable.strings Localizable.stringsdict .
?
:
public static let localization_var = "localization_key".localized
public static func localization_method(_ value1: String) -> String {
"localization_method_key".localized(with: value1)
}
localized :
var localized: String {
let localLocalisation = Self.localLocaliseBundle?.localizedString(
forKey: self,
value: nil,
table: nil
)
let serverLocalisation = Self.makeServerLocaliseBundle()?.localizedString(
forKey: self,
value: localLocalisation,
table: “Localizable.nocache”
)
return serverLocalisation ?? localLocalisation ?? self
}
;
, Documents, ;
, , , .
, (localized(with:)), :
func localized(with parameters: CVarArg...) -> String {
let correctLocalizedString: String = {
if localized.starts(with: "%#@") {
return localized
}
return localized
.replacingOccurrences(of: "%s", with: "%@")
.replacingOccurrences(
of: "(%[0-9])\\$s",
with: "$1@",
options: .regularExpression
)
}()
guard !correctLocalizedString.isEmpty else {
return self
}
return String(format: correctLocalizedString, arguments: parameters)
}
:
plural ;
, Lokalise, ;
, ;
, , .
: -, Localizable.stringsdict , ; -, , , plural . , localizedString(forKey:value:table:) plural , Localizable.stringsdict, __NSLocalizedString. plural . , .regularExpression replacingOccurencies(of:with:options:) String , , __NSLocalizedString.
, :
;
Lokalise , ;
, , , debug , Localisation.swift;
, , , ;
Lokalise;
, , production Lokalise , ;
production Lokalise;
.
production Lokalise Gitlab , , , , , .
, .
iOS Android
, , , iOS Android -. , iOS %@, Android %s. , , Android first Lokalise, iOS .
, - . , . . , .
, , .
, 2 “” - debug production. debug , , production - , debug production.
, , production . , - . : , Localisation.swift, . , , .
, Lokalise, - . , .
, , , debug production , . , , , .
, , - , . That’s all, Folks!