i18nとl10nの違い

💡 用語解説

  • i18n(Internationalization): 国際化 - テーマを翻訳可能にする準備
  • l10n(Localization): ローカライズ - 実際に特定の言語に翻訳すること

基本的な翻訳関数

WordPressには翻訳用の関数が用意されています。

主な翻訳関数

PHP// __() - 翻訳した文字列を返す $text = __('Hello World', 'mytheme'); // _e() - 翻訳した文字列を出力 _e('Welcome', 'mytheme'); // _x() - 文脈付き翻訳 _x('Post', 'noun', 'mytheme'); // 投稿(名詞) _x('Post', 'verb', 'mytheme'); // 投稿する(動詞) // _n() - 複数形対応 $count = 5; printf( _n('%s comment', '%s comments', $count, 'mytheme'), number_format_i18n($count) ); // esc_html__() - エスケープ付き翻訳 echo esc_html__('Safe Text', 'mytheme'); // esc_attr__() - 属性用エスケープ付き翻訳 echo '<input placeholder="' . esc_attr__('Enter text', 'mytheme') . '">';

⚠️ 重要な注意点

  • 第2引数のテキストドメイン('mytheme')は必須
  • 変数を含む文字列は sprintf() と組み合わせる
  • 出力時は必ずエスケープ関数を使う

テーマを翻訳可能にする準備

STEP 1: テキストドメインの設定

style.css/* Theme Name: My Theme Text Domain: mytheme Domain Path: /languages */

STEP 2: 翻訳ファイルの読み込み

functions.phpfunction mytheme_load_textdomain() { load_theme_textdomain('mytheme', get_template_directory() . '/languages'); } add_action('after_setup_theme', 'mytheme_load_textdomain');

STEP 3: ハードコードされたテキストを翻訳関数で囲む

Before(翻訳不可)<h1>Welcome to my site</h1> <p>Copyright 2026</p>
After(翻訳可能)<h1><?php esc_html_e('Welcome to my site', 'mytheme'); ?></h1> <p><?php echo esc_html__('Copyright', 'mytheme') . ' ' . date('Y'); ?></p>

翻訳ファイルの作成

必要なツール

  • Poedit: 翻訳エディタ(推奨)
  • WP-CLI: コマンドラインツール
  • Loco Translate: WordPressプラグイン

Poeditを使った翻訳手順

  1. Poeditをダウンロード

    https://poedit.net/ から無料版をダウンロードします。

  2. 新しい翻訳を作成

    「ファイル」→「新規」→「WordPressテーマから翻訳を作成」

  3. テーマフォルダを選択

    mythemeフォルダを選択して、言語を「日本語」に設定します。

  4. 翻訳する

    抽出された文字列を1つずつ翻訳していきます。

  5. 保存

    languagesフォルダに mytheme-ja.po と mytheme-ja.mo が生成されます。

WP-CLIを使った翻訳

POTファイルの生成

コマンドライン# テーマディレクトリに移動 cd wp-content/themes/mytheme # POTファイル生成 wp i18n make-pot . languages/mytheme.pot

POファイルの作成

コマンドライン# 日本語用POファイルを作成 msgint -i languages/mytheme.pot -o languages/mytheme-ja.po -l ja # MOファイルにコンパイル msgfmt languages/mytheme-ja.po -o languages/mytheme-ja.mo

実践的な翻訳例

変数を含む翻訳

PHP<?php $username = 'John'; // 悪い例(翻訳できない) echo 'Hello, ' . $username; // 良い例 printf( esc_html__('Hello, %s', 'mytheme'), esc_html($username) ); ?>

複数形の翻訳

PHP<?php $count = get_comments_number(); printf( _n( 'One comment', '%s comments', $count, 'mytheme' ), number_format_i18n($count) ); ?>

JavaScript内での翻訳

functions.phpfunction mytheme_enqueue_scripts() { wp_enqueue_script( 'mytheme-script', get_template_directory_uri() . '/js/script.js', array('jquery'), '1.0', true ); // JavaScriptに翻訳を渡す wp_localize_script('mytheme-script', 'mythemeL10n', array( 'confirmDelete' => __('Are you sure you want to delete?', 'mytheme'), 'loading' => __('Loading...', 'mytheme'), )); } add_action('wp_enqueue_scripts', 'mytheme_enqueue_scripts');
script.js// JavaScriptで翻訳を使用 if (confirm(mythemeL10n.confirmDelete)) { alert(mythemeL10n.loading); }

多言語プラグインとの統合

プラグイン 特徴 料金
WPML 最も人気、機能豊富 有料
Polylang 使いやすい、軽量 無料/有料
TranslatePress フロントエンド翻訳 無料/有料
qTranslate-XT シンプル 無料

言語切り替えメニューの実装

functions.phpfunction mytheme_language_switcher() { $languages = array( 'ja' => '日本語', 'en' => 'English', 'zh' => '中文', ); $current_lang = get_locale(); echo '<div class="language-switcher">'; foreach ($languages as $code => $name) { $class = ($current_lang === $code) ? 'current' : ''; echo sprintf( '<a href="%s" class="%s">%s</a>', home_url("/{$code}/"), $class, $name ); } echo '</div>'; }
header.php<nav class="language-nav"> <?php mytheme_language_switcher(); ?> </nav>

日付と数値のローカライズ

PHP<?php // 日付のローカライズ echo date_i18n('Y年n月j日', strtotime('2026-01-01')); // 出力: 2026年1月1日 // 数値のローカライズ echo number_format_i18n(1234567); // 日本語: 1,234,567 // ドイツ語: 1.234.567 // 通貨のフォーマット $price = 1234.56; echo sprintf( __('Price: %s', 'mytheme'), number_format_i18n($price, 2) ); ?>

RTL(右から左)言語への対応

アラビア語やヘブライ語などの対応です。

functions.phpfunction mytheme_rtl_support() { if (is_rtl()) { wp_enqueue_style( 'mytheme-rtl', get_template_directory_uri() . '/rtl.css' ); } } add_action('wp_enqueue_scripts', 'mytheme_rtl_support');
rtl.css/* RTL用のスタイル */ body { direction: rtl; text-align: right; } .site-header { padding-right: 2rem; padding-left: 0; } .menu { float: right; }

翻訳のベストプラクティス

⚠️ 避けるべきこと

  • 文字列を分割しない: __('Hello') . ' ' . __('World')
  • HTMLを含めない: __('<strong>Bold</strong>')
  • 変数を直接埋め込まない: __("Hello $name")

✅ 推奨される方法

  • 完全な文を翻訳: __('Hello World', 'mytheme')
  • プレースホルダー使用: sprintf(__('Hello %s', 'mytheme'), $name)
  • 文脈を提供: _x('Post', 'noun', 'mytheme')

まとめ

多言語対応により、以下のことが可能になります:

🚀 次のステップ

多言語対応をマスターしたら、最後にアクセシビリティを学んで、すべての人が使いやすいサイトを構築しましょう。