応用編
🌍 多言語対応(i18n)
WordPressテーマを翻訳可能にする方法を学びます。国際化(i18n)とローカライズ(l10n)の基本から、実践的な翻訳ファイルの作成まで習得しましょう。
難易度: ★★★☆☆ 中級〜上級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を使った翻訳手順
-
Poeditをダウンロード
https://poedit.net/ から無料版をダウンロードします。
-
新しい翻訳を作成
「ファイル」→「新規」→「WordPressテーマから翻訳を作成」
-
テーマフォルダを選択
mythemeフォルダを選択して、言語を「日本語」に設定します。
-
翻訳する
抽出された文字列を1つずつ翻訳していきます。
-
保存
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')✓
まとめ
多言語対応により、以下のことが可能になります:
- ✅ グローバルなサイト運営
- ✅ 世界中のユーザーにリーチ
- ✅ テーマの再利用性向上
- ✅ プロフェッショナルな品質
🚀 次のステップ
多言語対応をマスターしたら、最後にアクセシビリティを学んで、すべての人が使いやすいサイトを構築しましょう。