Skip to content

Instantly share code, notes, and snippets.

@alex-georgiou
Last active February 19, 2025 12:25
Show Gist options
  • Save alex-georgiou/48430da5b31501de6f8e58796b6183fe to your computer and use it in GitHub Desktop.
Save alex-georgiou/48430da5b31501de6f8e58796b6183fe to your computer and use it in GitHub Desktop.
Use Gemini to translate flutter .arb files to multiple languages
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');
}
}
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
#!/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
#!/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
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