Skip to content

Commit

Permalink
Add language support for en, de, es, fr, hi, pt, it, ja, ru, zh and m…
Browse files Browse the repository at this point in the history
…ore (#223)
  • Loading branch information
Fintasys authored Nov 14, 2024
1 parent 92bb072 commit b45a14c
Show file tree
Hide file tree
Showing 25 changed files with 62,637 additions and 16 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@
.idea/

build/

automation/descriptions.txt
automation/temp.xml
automation/temp
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 4.0.0
- Add localization support for following languages: en, de, es, fr, hi it, ja, pt, ru, zh
- Add script to generate language files for any language based on the official unucode organization translations
- Improve search feature to match new emoji name pattern based on keywords

## 3.1.0
- Added Emoji for Transgender Flag and Hugging People (thx to everypizza1)
- Replace `swapCategoryAndBottomBar` with `viewOrderConfig` to give more control over the order of each view (thx to coder-with-a-bushido)
Expand Down
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Yet another Emoji Picker for Flutter 🤩
- Skin Tone Support
- Custom-Font Support
- Search Option
- Localization (supporting 8 Languages)

[!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/fintasys)

Expand Down Expand Up @@ -227,6 +228,50 @@ Each component can also be completely customized individually:

- `BottomActionBarConfig` -> `customBottomActionBar`

## Localization
The package currently supports following languages: en, de, es, fr, hi, it, ja, pt, ru, zh.
In order to let the EmojiPicker choose the right language you need to pass the locale to the config:
``` dart
Config(
locale: const Locale("ja"),
)
```
In case you want to support additional languages, you need to create a copy of a emoji set file (see /lib/locales), translate it (optional use `/automation/create_emoji_set.sh` to help you) and adjust the config for `emojiSet`:
```dart
EmojiPicker(
config: Config(
emojiSet: _getEmojiLocale,
),
)
List<CategoryEmoji> _getEmojiLocale(Locale locale) {
switch (locale.languageCode) {
case "ja":
return emojiSetJapanese;
case "de":
return emojiSetGerman;
default:
return emojiSetEnglish;
}
}
```
Example for using `/automation/create_emoji_set.sh` for generating translation in terminal:
1. Fork the repository and open the directory from your terminal
2. Run command below
```
cd automation && ./create_emoji_set.sh pt Portuguese
```
Feel free to create an issue if you think a specific language should be supported by default. We keep the languages limited for now to avoid the package size growing unnecesserily large.

In case you want to support only a single language you can just return the same EmojiSet for all locales.
```
List<CategoryEmoji> _getEmojiLocale(String locale) {
return emojiSetEnglish;
}
```
Using a single EmojiSet will reduce the package size by about 2 MB.
If you prefer to use the old EmojiSet (version 3 and below), you can return `defaultEmojiSet`.

## Extended usage with EmojiPickerUtils

Find usage example [here](https://github.com/Fintasys/emoji_picker_flutter/blob/master/example/lib/main_key.dart)
Expand Down
111 changes: 111 additions & 0 deletions automation/create_emoji_set.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/bin/bash

# Check for locale and const name arguments
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: $0 <locale> <const_name>"
exit 1
fi

locale="$1"
const_name="$2" # New variable to store the const name
url="https://raw.githubusercontent.com/unicode-org/cldr/main/common/annotations/${locale}.xml"
template_file="../lib/src/default_emoji_set.dart"

output_dir="../lib/locales"
output_file="$output_dir/emoji_set_${locale}.dart"

# Function to decode HTML entities
decode_html_entities() {
local input="$1"

# Replace common HTML entities with their ASCII equivalents
local decoded=$(echo "$input" | sed -e 's/&amp;/\&/g' \
-e 's/&lt;/</g' \
-e 's/&gt;/>/g' \
-e 's/&quot;/"/g' \
-e "s/&apos;/'/g" \
-e 's/&nbsp;/ /g')

echo "$decoded"
}

# Create the output directory if it doesn't exist
mkdir -p "$output_dir"

# Fetch the XML file (corrected)
curl -s "$url" >temp.xml

# Check if curl was successful
if [[ $? -ne 0 ]]; then
echo "Error downloading XML file for locale: $locale"
rm temp.xml # Cleanup even if there was an error.
exit 1 # Exit with an error code.
fi

# Extract descriptions into a temporary file
grep '<annotation cp="' temp.xml | perl -CSD -ne 'print "$1:$2\n" if /<annotation cp="([^"]+)"[^>]*>([^<]+)<\/annotation>/;' >descriptions.txt

# Create the output file based on the template
cat "$template_file" | sed "s/defaultEmojiSet/emojiSet$const_name/" | while read line; do

if [[ "$line" == *"Emoji("* ]] && [[ "$line" != *"CategoryEmoji("* ]]; then
#emoji=$(echo "$line" | cut -d "'" -f 2)
emoji=$(echo "$line" | sed "s/.*Emoji('\([^']*\)'.*/\1/")
original_description=$(echo "$line" | sed "s/.*Emoji('\(.*\)', '\(.*\)'.*/\2/")
indent=$(echo "$line" | sed 's/[^[:space:]].*//')
hasSkinTone=$(echo "$line" | grep -q "hasSkinTone: true" && echo "hasSkinTone: true" || echo "")

get_description() {
local emoji="$1"
local description=$(awk -F':' -v emoji="$emoji" '{gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1); gsub(/^[[:space:]]+|[[:space:]]+$/, "", emoji)} $1 == emoji {print $2; exit}' descriptions.txt)
local decodedDescription=$(decode_html_entities "$description")
echo "$decodedDescription"
}

description=$(get_description "$emoji")

# If description is empty, try component-wise search for combined emoji
if [[ -z "$description" ]]; then
# Split into components, handling ZWJ correctly for splitting
emoji_parts=($(echo "$emoji" | perl -CSD -ne 's/\x{200D}/ /g; s/[\x{FE0E}\x{FE0F}\x{200C}\x{200D}]//g; print for split //, $_'))

# Combine component descriptions
description=""
for part in "${emoji_parts[@]}"; do

part_description=$(get_description "$part")
if [[ -n "$part_description" ]]; then
description+="$part_description "
fi
done

if [[ -n "$description" ]]; then
echo "Processed combined emoji: $emoji (Description: $description)" >&2
else
description="$original_description"
#Output bytes of emoji for debugging
#echo -n "$emoji" | xxd -p >&2
echo "Emoji $emoji not found in locale $locale - using default description" >&2
fi

else
echo "Processed emoji: $emoji (Description: $description)" >&2
fi

printf "%sEmoji('%s', '%s', %s),\n" "$indent" "$emoji" "$description" "$hasSkinTone"

else
echo "$line"
fi

done >"$output_file"

# Clean up temporary files
rm temp.xml
rm temp
rm descriptions.txt

# Format file
dart format "$output_file"

echo "Generated $output_file"
54 changes: 54 additions & 0 deletions automation/generate_all_locales.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
outputDir="../lib/locales"
outputFile="$outputDir/default_emoji_set_locale.dart"

echo "Generating all locales"
>"$outputDir/emoji_set.dart"
echo "====================="

locales=(
"de German"
"en English"
"es Spanish"
"fr France"
"hi Hindi"
"it Italian"
"ja Japanese"
"pt Portuguese"
"ru Russian"
"zh Chinese"
)

for locale in "${locales[@]}"; do
IFS=" " read code lang <<<"$locale" # Split the locale string into code and language
echo "$lang - $code"
./create_emoji_set.sh "$code" "$lang" >/dev/null 2>&1
echo "export 'package:emoji_picker_flutter/locales/emoji_set_$code.dart';" >>"$outputDir/emoji_set.dart"
done

# Create the default emoji set locale file and add the import statement
>"$outputFile"
echo "import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';" >>"$outputFile"
echo "import 'package:flutter/material.dart';" >>"$outputFile"

# Start writing the getDefaultEmojiLocale method
echo >>"$outputFile"
echo "/// Default method for locale selection" >>"$outputFile"
echo "List<CategoryEmoji> getDefaultEmojiLocale(Locale locale) {" >>"$outputFile"
echo " switch (locale.languageCode) {" >>"$outputFile"

# Dynamically add case statements
for locale in "${locales[@]}"; do
IFS=" " read code lang <<<"$locale" # Split the locale string into code and language
emojiSetVar="emojiSet$lang"
echo " case '$code':" >>"$outputFile"
echo " return $emojiSetVar;" >>"$outputFile"
done

# Default case
echo " default:" >>"$outputFile"
echo " return emojiSetEnglish;" >>"$outputFile"
echo " }" >>"$outputFile"
echo "}" >>"$outputFile"

echo "====================="
echo "All locales generated"
1 change: 1 addition & 0 deletions lib/emoji_picker_flutter.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
library emoji_picker_flutter;

export 'package:emoji_picker_flutter/locales/emoji_set.dart';
export 'package:emoji_picker_flutter/src/bottom_action_bar/bottom_action_bar.dart';
export 'package:emoji_picker_flutter/src/bottom_action_bar/bottom_action_bar_config.dart';
export 'package:emoji_picker_flutter/src/bottom_action_bar/default_bottom_action_bar.dart';
Expand Down
30 changes: 30 additions & 0 deletions lib/locales/default_emoji_set_locale.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
import 'package:flutter/material.dart';

/// Default method for locale selection
List<CategoryEmoji> getDefaultEmojiLocale(Locale locale) {
switch (locale.languageCode) {
case 'de':
return emojiSetGerman;
case 'en':
return emojiSetEnglish;
case 'es':
return emojiSetSpanish;
case 'fr':
return emojiSetFrance;
case 'hi':
return emojiSetHindi;
case 'it':
return emojiSetItalian;
case 'ja':
return emojiSetJapanese;
case 'pt':
return emojiSetPortuguese;
case 'ru':
return emojiSetRussian;
case 'zh':
return emojiSetChinese;
default:
return emojiSetEnglish;
}
}
10 changes: 10 additions & 0 deletions lib/locales/emoji_set.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export 'package:emoji_picker_flutter/locales/emoji_set_de.dart';
export 'package:emoji_picker_flutter/locales/emoji_set_en.dart';
export 'package:emoji_picker_flutter/locales/emoji_set_es.dart';
export 'package:emoji_picker_flutter/locales/emoji_set_fr.dart';
export 'package:emoji_picker_flutter/locales/emoji_set_hi.dart';
export 'package:emoji_picker_flutter/locales/emoji_set_it.dart';
export 'package:emoji_picker_flutter/locales/emoji_set_ja.dart';
export 'package:emoji_picker_flutter/locales/emoji_set_pt.dart';
export 'package:emoji_picker_flutter/locales/emoji_set_ru.dart';
export 'package:emoji_picker_flutter/locales/emoji_set_zh.dart';
Loading

0 comments on commit b45a14c

Please sign in to comment.