Last active
February 19, 2025 12:25
-
-
Save alex-georgiou/48430da5b31501de6f8e58796b6183fe to your computer and use it in GitHub Desktop.
Use Gemini to translate flutter .arb files to multiple languages
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:io'; | |
import 'package:integration_test/integration_test_driver_extended.dart'; | |
Future<void> main() async { | |
try { | |
await integrationDriver( | |
onScreenshot: (screenshotName, screenshotBytes, [args]) async { | |
final File image = await File('play/assets/screenshots/$screenshotName.png').create(recursive: true); | |
image.writeAsBytesSync(screenshotBytes); | |
return true; | |
}, | |
); | |
} catch (e) { | |
print('Error occured: $e'); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Afrikaans | af | af | |
---|---|---|---|
Amharic | am | am | |
Arabic | ar | ar | |
Azerbaijani | az-AZ | az | |
Belarusian | be | be | |
Bulgarian | bg | bg | |
Bangla | bn-BD | bn | |
Catalan | ca | ca | |
Czech | cs-CZ | cs | |
Danish | da-DK | da | |
German | de-DE | de | |
Greek | el-GR | el | |
English | en | en | |
Spanish (Spain) | es-ES | es | |
Estonian | et | et | |
Basque | eu-ES | eu | |
Persian | fa | fa | |
Finnish | fi-FI | fi | |
Filipino | fil | fil | |
French (France) | fr-FR | fr | |
Galician | gl-ES | gl | |
Gujarati | gu | gu | |
Hindi | hi-IN | hi | |
Croatian | hr | hr | |
Hungarian | hu-HU | hu | |
Armenian | hy-AM | hy | |
Indonesian | id | id | |
Icelandic | is-IS | is | |
Italian | it-IT | it | |
Hebrew | iw-IL | iw | |
Japanese | ja-JP | ja | |
Georgian | ka-GE | ka | |
Kazakh | kk | kk | |
Khmer | km-KH | km | |
Kannada | kn-IN | kn | |
Korean | ko-KR | ko | |
Kyrgyz | ky-KG | ky | |
Lao | lo-LA | lo | |
Lithuanian | lt | lt | |
Latvian | lv | lv | |
Malagasy | mg | mg | |
Macedonian | mk-MK | mk | |
Malayalam | ml-IN | ml | |
Mongolian | mn-MN | mn | |
Marathi | mr-IN | mr | |
Malay | ms | ms | |
Malay (Malaysia) | ms-MY | ms | |
Burmese | my-MM | my | |
Nepali | ne-NP | ne | |
Dutch | nl-NL | nl | |
Norwegian | no-NO | no | |
Punjabi (Gurmukhi) | pa-IN | pa-IN | |
Punjabi (Shahmukhi) | pa-PK | pa-PK | |
Polish | pl-PL | pl | |
Portuguese (Portugal) | pt-PT | pt | |
Romansh | rm | rm | |
Romanian | ro | ro | |
Russian | ru-RU | ru | |
Sinhala | si-LK | si | |
Slovak | sk | sk | |
Slovenian | sl | sl | |
Albanian | sq | sq | |
Serbian | sr | sr | |
Swedish | sv-SE | sv | |
Swahili | sw | sw | |
Tamil | ta-IN | ta | |
Telugu | te-IN | te | |
Thai | th | th | |
Turkish | tr-TR | tr | |
Ukrainian | uk | uk | |
Urdu | ur | ur | |
Vietnamese | vi | vi | |
Chinese (Simplified) | zh-CN | zh | |
Zulu | zu | zu |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Use Gemini to translate flutter .arb files to multiple languages. | |
gemini_key=$(cat gemini_key) | |
arb=$(cat "lib/l10n/app_en.arb") | |
while IFS=',' read -r col1 col2 col3 rest_of_line; do | |
language="${col1//\"/}" | |
locale="${col2//\"/}" | |
locale_prefix="${col3//\"/}" | |
output_file="lib/l10n/app_${locale_prefix}.arb" | |
if [ ! -e "$output_file" ]; then | |
if [[ "$locale" != "en" ]]; then | |
echo "Language: $language Language code: $locale" | |
# main prompt | |
request="I am the author of an Android app titled 'Simplest Percentage Calculator'." | |
request="$request The app does Foo, Bar and Baz things for the user. " # TODO provide a short description of the app here to give context | |
request="$request I need you to translate the application strings from English to $language." | |
request="$request Please translate the following .arb file to $language ($locale locale)." | |
request="$request Only output the JSON data without any other text." | |
request="$request Preserve the keys and only translate the values." | |
request="$request Preserve the substrings in square brackets or curly brackets, i.e. do not translate the [foo] parts or the {bar} parts." | |
# append english arb file | |
request="$request $arb" | |
# escape json for embedding into json | |
request=$(echo "$request" | jq -Rsa .) | |
# embed json into json | |
request="{\"contents\": [{\"parts\":[{\"text\": $request}]}],\"generationConfig\": { \"response_mime_type\": \"application/json\" }}" | |
echo "$request" | jq . | |
response=$(curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${gemini_key}" \ | |
-H 'Content-Type: application/json' \ | |
-X POST \ | |
-d "$request") | |
# remove gemini metadata | |
response=$(echo "$response" | jq .candidates[0].content.parts[0].text ) | |
# remove prefix | |
response="${response#\"\`\`\`json\\n}" | |
#remove suffix | |
response=${response%\\n\`\`\`\\n\"} | |
# unescape | |
response=$(echo "$response" | sed 's/^"//; s/\\n//g; s/"$//; s/\\"/"/g' | jq .) | |
# write translation file or show error | |
if echo "$response" | jq . ; then | |
echo "$response" >"$output_file" | |
else | |
echo "Error: Could not write $language translation to $output_file" | |
fi | |
fi | |
fi | |
done < "make_arb_files.csv" | |
# The Punjabi language has two scripts, the Shahmukhi and the Gurmukhi alphabet. | |
# Here we set a default to be used if the device's locale is not specific. | |
cp lib/l10n/app_pa-PK.arb lib/l10n/app_pa.arb |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
for arb in lib/l10n/*.arb; do | |
noext=${arb%.arb} | |
locale=${noext#lib/l10n/app_} | |
if test -f play/assets/screenshots/screenshot-$locale-1.png; then | |
continue | |
fi | |
flutter drive --driver=test_driver/integration_test.dart --target=test/screenshots_test.dart --dart-define=TEST_LOCALE=$locale | |
done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:io'; | |
import 'package:flutter/foundation.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter_test/flutter_test.dart'; | |
import 'package:integration_test/integration_test.dart'; | |
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | |
// TODO import your app here | |
takeScreenShot( | |
{required IntegrationTestWidgetsFlutterBinding binding, | |
required WidgetTester tester, | |
required String screenShotName}) async { | |
if (kIsWeb) { | |
await binding.takeScreenshot(screenShotName); | |
return; | |
} else if (Platform.isAndroid) { | |
await binding.convertFlutterSurfaceToImage(); | |
await tester.pumpAndSettle(); | |
} | |
await binding.takeScreenshot(screenShotName); | |
} | |
void main() { | |
final binding = IntegrationTestWidgetsFlutterBinding.ensureInitialized(); | |
String localeStr = | |
const String.fromEnvironment('TEST_LOCALE', defaultValue: 'en_US'); | |
var parts = localeStr.split('_'); | |
Locale locale; | |
if (parts.length == 2) { | |
locale = Locale(parts.first,parts.last); | |
} else { | |
locale = Locale(parts.first); | |
} | |
testWidgets('take screenshot 1', (WidgetTester tester) async { | |
// Load app widget. | |
await tester.pumpWidget(MaterialApp( | |
title: 'Foo App', // TODO change this | |
localizationsDelegates: AppLocalizations.localizationsDelegates, | |
supportedLocales: AppLocalizations.supportedLocales, | |
locale: locale, | |
debugShowCheckedModeBanner: false, | |
home: Builder(builder: (context) { | |
return const FooAppScreen(); // TODO change this | |
}))); | |
await tester.pumpAndSettle(); | |
// TODO modify this to create a screenshot for your app | |
// Here we go to the app's first tab and enter the text "USER INPUT" | |
final tab1 = find.byKey(const Key('tab1')); | |
expect(tab1, findsOneWidget); | |
await tester.tap(tab1); | |
await tester.pumpAndSettle(); | |
final input1 = find.byKey(const Key('input1')); | |
expect(input1, findsOneWidget); | |
await tester.enterText(input1, 'USER INPUT'); | |
await tester.pumpAndSettle(); | |
//generate screenshot | |
await takeScreenShot( | |
binding: binding, | |
tester: tester, | |
screenShotName: "screenshot-$locale-1"); | |
await tester.pumpAndSettle(); | |
}); | |
testWidgets('take screenshot 2', (WidgetTester tester) async { | |
// TODO Do the same as above to navigate in your app towards the second screenshot | |
//generate screenshot | |
await takeScreenShot( | |
binding: binding, | |
tester: tester, | |
screenShotName: "screenshot-$locale-2"); | |
await tester.pumpAndSettle(); | |
}); | |
// TODO Do the same for more screenshots. Ideally you want 3 or 4 screenshots in total. | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment