Hello! If your application supports different languages, then you probably encountered problems related to localization: errors in writing keys, missing values for languages, the need to rebuild the application in case of emergency translation edits. Not the most pleasant moments of development, is it?
This article will discuss how localization works in Vivid.Money: we will tell you which tool for localization you chose, what problems you encountered and how they were solved.
For a better understanding of the specifics of the project, you can familiarize yourself with this material, and we suggest starting this article without further ado.
Which localization method did you choose
Our localization requirements include the following points:
Synchronization between platforms (iOS, Android, Backend) for a single source of truth;
Checking the correct spelling of the keys used during compilation to eliminate the possibility of making a typo in the key name;
No need for developers to independently introduce localizations for different languages in order for developers to spend more time doing what they should - to implement features;
Ease of interaction with translators;
The ability to change key values without rebuilding the application.
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!