Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add language support for en, de, es, fr, hi, pt, it, ja, ru, zh and more #223

Merged
merged 24 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading