BLOG ブログ


2025.06.23 TECH

CSSの疑似要素の多言語化について考えてみた

CSSの::before疑似要素を用いて、要素の前に何かを表示する方法があります。contentプロパティに文字を入れてテキストを出すこともできますが、ふと、「このテキストを多言語化対応するにはどうすればいいのだろう」と思い浮かんだので、どんなやり方があるか考えてみることにしました。

先に今回書いたコードを載せておきます。

ここではcodepenを使用する都合上、main要素にlang属性を指定していますが、もちろんhtml要素のlang属性を指定しても大丈夫です。また、ボタン押下によってlang属性を切り替えていますが、ここもページ読み込み時にphpなどでhtml要素のlang属性を切り替えるのでも行けます。

htmlの属性で指定する

まずはhtmlの属性でテキストを指定し、CSSでそれを読ませてみることにしました。

<main class="lang-setting" lang="ja">
  <h1 class="ttl"
    data-ja="主題"
    data-ko="주제"
    data-ru="предмет"
    data-en="subject">
    タイトル
  </h1>
</main>
main[lang="ja"] {
  .ttl {
    &::before{
      content: attr(data-ja)':';
    }
  }
}
main[lang="ko"] {
  .ttl {
    &::before{
      content: attr(data-ko)':';
    }
  }
}
// ......

やっていることは単純で、main要素のlang属性に合わせてdata-jaやdata-koをattr()で読んであげているだけです。attr()はCSSの関数で、任意の属性を読み取ることができます。あとはJSでmain要素のlang属性を書き換えれば、lang="ko"ならdata-koの中身が、lang="ru"ならdata-ruの中身が画面に表示されます。

これでも一応言語に合わせて文言を変えることはできるのですが、::beforeで指定している箇所が多い場合、そのすべてにdata属性を振るのは流石に面倒です。他にも方法はないでしょうか。

CSSで指定する

次に、CSSのcontentに直接文言を指定してみることにしました。

<main class="lang-setting" lang="ja">
  <section class="sec">
    <h2 class="ttl">タイトル</h2>
    <p>本文本文本文本文</p>
  </section>
</main>
main[lang="ja"] {
  .sec {
    > .ttl{
      &::before{
        content: '副題:';
      }
    }
  }
}
main[lang="ko"] {
  .sec {
    > .ttl{
      &::before{
        content: '부제:';
      }
    }
  }
}

同じ内容の::beforeを出す箇所が沢山ある場合、この方が一括指定できて楽そうに見えます。

しかしです。そもそも多言語化対応をするようなケースにおいて、htmlやCSSに直接文言を書くのは、見通しも悪くなるし、管理も煩雑になりそうです。もっと他の方法もないでしょうか。

JSで対応する

多言語化対応をするときは、大抵JSONでデータを持っているはずです。そこで、JSでオブジェクトとしてデータを取得したテイで、見出しにdata属性を付与してみることにします。

<main class="lang-setting" lang="ja">
  <section class="sec-2nd">
    <h3 class="ttl js-subhead">タイトル</h3>
    <p>本文本文本文本文本文本文本文本文</p>
  </section>
</main>
main { 
  .sec-2nd {
    > .ttl {
      &::before{
        content: attr(data-lang);
      }
    }
  }
}
const subhead = {
  ja: '小見出し:',
  ko: '작은 표제:',
  ru: 'подзаголовок: ',
  en: 'subhead: '
}

let langSetting = document.querySelector('.lang-setting');

const items = document.querySelectorAll('.js-subhead');

items.forEach(item => {
  switch(langSetting.getAttribute('lang')) {
    case 'ja':
      item.dataset.before = subhead.ja;
      break;
    case 'ko':
      item.dataset.before = subhead.ko;
      break;
    case 'ru':
      item.dataset.before = subhead.ru;
      break;
    case 'en':
      item.dataset.before = subhead.en;
      break;
  }
})

上のコードでは、lang属性を読んでdata-before属性を変更する部分だけ抜き出しています。実際は利用方法に応じて、DOMContentLoadedやclickイベントなどに紐づけてください。codepenの方ではclickで実行しています。

この方法ならテキストを一か所で管理できるため、対応箇所が多い場合は便利そうです。

おわりに

実際に::beforeに多言語化対応が必要になるようなテキストを入れるか? と言われるとまあ滅多にないとは思うのですが、やりようはあるという実験でした。

実は最初にやり方を考え始めたとき、JSから::beforeを操作することはできないので(スタイルの取得などは可能ですが)、JSで多言語化するのは無理ではないかと思っていました。ですがdata属性を操作することは可能なので、こちらを使って::beforeの中身を変更することができました。

他にも、できない思っていたことにも別の道があったりするので、色々試していきたいですね。


一覧に戻る


LATEST ARTICLE 最新の記事

CATEGORY カテゴリー