langly is a command-line tool written in Go for converting .arb files (used in Flutter for localization) into platform-specific formats for iOS and Android. The tool generates Localizable.strings and Localizable.stringsdict files for iOS, and strings.xml files for Android, allowing translations to be managed and utilized in native mobile app projects.
- Convert
.arbfiles to iOSLocalizable.strings - Convert
.arbfiles to iOSLocalizable.stringsdict(inplistformat) for handling plurals - Convert
.arbfiles to Androidstrings.xml
To install the tool, you need to have Go installed on your machine. Clone the repository and build the binary:
git clone https://github.com/phillippbertram/langly.git
cd langly
go build -o langlyTo convert an .arb file to iOS Localizable.strings and Localizable.stringsdict files:
./langly ios examples/arb -o ./examples/ios/langly/langly/LocalizationsTo convert an .arb file to Android strings.xml file:
./langly android examples/arb -o ./examples/android/app/src/main/resGiven an .arb file example_en.arb:
{
"@@locale": "en",
"app_title": "Fast Shopping",
"@app_title": {
"description": "Shown on top of the screen."
},
"list_item_no_name": "No name",
"@list_item_no_name": {
"description": "When the item has no/empty name."
},
"list_item_done_ago": "done {when}",
"@list_item_done_ago": {
"description": "Small caps date when item was marked as done.",
"placeholders": {
"when": {
"type": "String",
"example": "a minute ago"
}
}
},
"delete_shopping_list_dialog_body": "Do you really want to delete {list_name} shopping list? This operation cannot be undone.",
"@delete_shopping_list_dialog_body": {
"placeholders": {
"list_name": {
"type": "String",
"example": "Groceries"
}
}
},
"nWombats": "{count, plural, =0{no wombats} =1{1 wombat} other{{count} wombats}}",
"@nWombats": {
"description": "A plural message",
"placeholders": {
"count": {
"type": "Int"
}
}
},
"pageHomeInboxCount": "{number, plural, zero{You have no new messages} one{You have 1 new message} other{You have {number} new messages}}",
"@pageHomeInboxCount": {
"description": "New messages number on the Home screen",
"placeholders": {
"number": {}
}
}
}Running the tool for iOS:
./langly ios ./arb -o ./outputThis generates Localizable.strings:
"app_title"="Fast Shopping";
"delete_shopping_list_dialog_body"="Do you really want to delete %@ shopping list? This operation cannot be undone.";
"list_item_done_ago"="done %@";
"list_item_no_name"="No name";
and Localizable.stringsdict in the specified output directory:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>nWombats</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>one</key>
<string>1 wombat</string>
<key>other</key>
<string>%d wombats</string>
<key>zero</key>
<string>no wombats</string>
</dict>
</dict>
<key>pageHomeInboxCount</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@number@</string>
<key>number</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>d</string>
<key>other</key>
<string>You have %d new messages</string>
</dict>
</dict>
</dict>
</plist>Running the tool for Android:
./langly android ./arb -o ./outputThis generates strings.xml in the specified output directory.
<resources>
<string name="app_title">Fast Shopping</string>
<string name="delete_shopping_list_dialog_body">Do you really want to delete %s shopping list? This operation cannot be undone.</string>
<string name="list_item_done_ago">done %s</string>
<string name="list_item_no_name">No name</string>
<plurals name="nWombats">
<item quantity="other">%d wombats</item>
<item quantity="zero">no wombats</item>
<item quantity="one">1 wombat</item>
</plurals>
<plurals name="pageHomeInboxCount">
<item quantity="other">You have %d new messages</item>
</plurals>
</resources>This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please open an issue or submit a pull request for any bugs or features.