Slide 1

Slide 1 text

Linterでチョット安心 iOS多言語化対応 2023/07/12 (水) YUMEMI.grow Mobile #5 @konifar

Slide 2

Slide 2 text

多言語化対応 やってますか?

Slide 3

Slide 3 text

https://twitter.com/konifar/status/1678867068203208707

Slide 4

Slide 4 text

今日は途中から 多言語化する時の話です

Slide 5

Slide 5 text

ChatGPTと翻訳

Slide 6

Slide 6 text

Chat GPTによってフローが大きく変わりうる ● 言語にもよるが、 文脈も考慮してそれなりの精度で翻訳可能 ● Localizable.strings のまま翻訳可能 ○ テキスト部分を抽出して翻訳依頼を出し、 プロジェクトに適用するという地味にめんどくさい部 分をやらなくてもよい。 これはかなり嬉しい

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

じつに愛らしい...!

Slide 9

Slide 9 text

問題点

Slide 10

Slide 10 text

たまに賢すぎる

Slide 11

Slide 11 text

たまに賢すぎる問題 ● タイポらしきものを修正してくれたり、 文脈を高度に読み取ってくれたりする ○ 「100%%保証」 => 「100%保証」 ○ 「"freind"="友達"」 => 「"friend"="Friend"」 ○ 「〜(略)〜%@」 => 「〜(略)〜 you」 (文脈は合ってる) ● すごいけど、 今それをされると困る

Slide 12

Slide 12 text

ニンゲンでも同じ ● ChatGPTの場合にはプロンプトの工夫でかなり改善できるはずだが、 余計な ことをしていないかのチェックはしないと不安ではある ● ChatGPTを使わず、 社内や外部で人力で翻訳をする場合でも同じようなミス は起こりうる ● 機械的にチェックできるものはLinterでチェックするべき

Slide 13

Slide 13 text

Linterでチョット安心 iOS多言語化対応

Slide 14

Slide 14 text

localizable_strings_checker.rb ● ja.lproj/Localizable.strings を正として次のチェックを行うスクリプト ○ ja のキーと同じキーが多言語のstringsファイルにも存在するか ○ ja のコメントと同じコメントが他言語にもあるか ○ ja の値に 「%%」、 「%s」、 「%@」、 「%d」 がある時、他言語にも同じ個数含まれるか ○ 値に 「%」 だけの文字が含まれていないか https://github.com/konifar/i18nLocalizableStringsExample/blob/main/scripts/localization/localizable_strings.checker.rb

Slide 15

Slide 15 text

# https://github.com/rylev/apfel を使って Localizable.strings を読み込みます require 'apfel'

Slide 16

Slide 16 text

# https://github.com/rylev/apfel を使って Localizable.strings を読み込みます require 'apfel' # (略) # 日本語の Localizable.stringsを読み込む ja_path = "#{root_dir}/ja.lproj/Localizable.strings" ja_file = Apfel.parse(ja_path) puts "Loaded #{ja_path}, key counts: #{ja_file.keys.length}" # % がひとつだけ入っている文字列がないかを確認 has_single_percent = check_single_percent_string(ja_file.key_values)

Slide 17

Slide 17 text

def check_single_percent_string(key_values) puts " Check no values contain only '%' character." has_error = false key_values.each do |key_value| key = key_value.keys.first value = key_value.values.first # 正規表現で愚直にチェック has_single_percent = value.match(/(?

Slide 18

Slide 18 text

# 他の言語のファイルをひとつひとつチェック Find.find(root_dir) do |path| if path =~ /.*\.lproj\/Localizable.strings$/ && path !~ /ja\.lproj/ other_file = Apfel.parse(path) puts "Loaded #{path}, key counts: #{other_file.keys.length}" # 1. ja のキーと同じキーが多言語のstringsファイルにも存在するか is_same_keys = check_same_keys(ja_file.keys, other_file.keys) # 2. ja のコメントと同じコメントが他言語にもあるか is_same_comments = check_same_comments(ja_file.comments, other_file.comments) # 3. ja の値に 「%%」、 「%s」、 「%@」、 「%d」 がある時、他言語にも同じ個数含まれるか no_special_strings_diff = check_replace_strings(ja_file.key_values, other_file.key_values) # 4. 値に 「%」 だけの文字が含まれていないか has_single_percent = check_single_percent_string(other_file.key_values) has_error = !is_same_keys || !is_same_comments || !no_special_strings_diff || !has_single_percent if has_error exit 1 end puts " No errors! Perfect!" end end

Slide 19

Slide 19 text

GitHub Actionsで動かす

Slide 20

Slide 20 text

name: lint-i18n-strings # (トリガは省略) jobs: lint: # (checkout や bundle install のstepは省略) - name: Lint Localizable.strings run: |- # Embedded framework でモジュール分割しているケースもあるので対象を配列で指定 projects=( "i18nLocalizableStringsExample" ) # ぐるぐる回して実行するだけ for project in "${projects[@]}" do echo "Start lint to $project" ruby ./scripts/localization/localizable_strings_checker.rb "$project/Languages" done https://github.com/konifar/i18nLocalizableStringsExample/blob/main/.github/workflows/lint-i18n.strings.yml

Slide 21

Slide 21 text

https://github.com/konifar/i18nLocalizableStringsExample/actions/runs/5527359783/jobs/10083024897 <= % がひとつだけの値が含まれていた <= 日本語のstringsだけにしかないキーがあった <= % がひとつだけの値が含まれていた Pull Request時にエラーで検知

Slide 22

Slide 22 text

心穏やかにガンガン 多言語化を進められる

Slide 23

Slide 23 text

安定してきたら gem や GitHub Actions を 作るかもしれません

Slide 24

Slide 24 text

ありがとうございました