Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Linterでチョット安心 iOS多言語化対応 / ios-i18n-linter

Linterでチョット安心 iOS多言語化対応 / ios-i18n-linter

YUMEMI.grow Mobile #5 の LT資料です。
https://yumemi.connpass.com/event/288628/

konifar

July 12, 2023
Tweet

More Decks by konifar

Other Decks in Programming

Transcript

  1. たまに賢すぎる問題 • タイポらしきものを修正してくれたり、 文脈を高度に読み取ってくれたりする ◦ 「100%%保証」 => 「100%保証」 ◦ 「"freind"="友達"」

    => 「"friend"="Friend"」 ◦ 「〜(略)〜%@」 => 「〜(略)〜 you」 (文脈は合ってる) • すごいけど、 今それをされると困る
  2. 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
  3. # 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)
  4. 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(/(?<!%)%(?![%]|[@]|[d]|[s]|[f]|[[0-9]$@]|[[0-9]$d]|[[0-9]$s]|[[0-9]$f])/) if has_single_percent has_error = true puts " key[#{key}] 's value have only '%' character." end end !has_error end
  5. # 他の言語のファイルをひとつひとつチェック 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
  6. 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