いろいろ調べたのでメモ的に。
前提と実現したいこと
- 割引分の価格を表示する(割引計算をテーマ側で行う)
上記の前提で以下のような動作を実現を目指しました。
- テーマ内蔵の通貨スイッチャーを考慮し、通貨単位の変化に対応した価格表示を行う
- ユーロ、アメリカドル、カナダドル、日本円が対象(例示のために選択しただけ)
以降記載するサンプルコードは、オプションの有無に関わらず正確な価格がJSで取得できている前提のコードとなります。
本来はオプションの有無やオプション変更を考慮して価格を取得しなければならないので、サンプルコードはそういったコードの中に組み込む一つという位置付けです。
サンプルコード
// 以下のように必要な箇所に書いて用いる想定
// amountには10000のような補助単位を基本にした価格の値が入る想定
changeByCurrency( amount );
// 通貨表示用の関数
function changeByCurrency( amount ) {
// 補助単位を通常の単位に戻す
// 例: 10000 → 100.00 (10000セントを100ドルに戻すなど)
amount = amount / 100;
amount = amount.toFixed(2);
// 数値に変換
amount = Number(amount);
// 価格の数値を入れて使い回す
let numberFormat = '';
// 通貨がユーロ、アメリカドル、カナダドル、日本円の4つで確定している前提
// Shopify.currency.activeで現在選択中の通貨単位が取得可能
// アプリを使った通貨スイッチャーでも必ずこの値が取れるのかは不明
if ( Shopify.currency.active === 'EUR') {
// ユーロに変換できればよいので指定国ないが、設定しないと動作しないので適当にドイツを選ぶ
const formatter = new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR'
});
numberFormat = formatter.format(amount);
// ユーロは 100 € のように後ろにスペースと通貨単位がつくので、これを€100のような表示に変更する
numberFormat = numberFormat.replace(' ', '');
numberFormat = numberFormat.replace('€', '');
numberFormat = '€' + numberFormat;
} else if ( Shopify.currency.active === 'CAD') {
formatter = new Intl.NumberFormat('en-CA', {
style: 'currency',
currency: 'CAD'
});
numberFormat = formatter.format(amount);
} else if ( Shopify.currency.active === 'JPY') {
formatter = new Intl.NumberFormat('ja-JP', {
style: 'currency',
currency: 'JPY'
});
numberFormat = formatter.format(amount);
} else if ( Shopify.currency.active === 'USD') {
formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
numberFormat = formatter.format(amount);
}
return numberFormat;
}
通貨の補助単位に関しては以下の記事にまとめています。
通貨ごとに位の区切り記号が違ったり、テーマ(や使われているライブラリ)ごとに通貨表記が違うので、テーマ内蔵の仕組みを流用するか同じ仕組みを導入する以外では、replaceで置換を行うなど整形する必要があるでしょう。
なお、テーマごとに違いがあるかもしれませんが、価格を含めた商品の詳細(厳密にはproductオブジェクト)は以下のようなデータ属性の付いたスクリプトタグ内に出力されています。
そのためJSでストアフロントに情報を追加する場合は、ここのJSONを取得して用いるのが基本になると思います。
<script type="application/json" data-product-json>
{
"product":{省略},
"selected_variant_id": xxxxxx
}
</script>
NumberFormatによる通貨単位の位置変更
var numberString = formatter.formatToParts(number).map(({type, value}) => {
switch (type) {
case 'currency': return `<strong>${value}</strong>`;
default : return value;
}
}).reduce((string, part) => string + part);
上記を利用すれば位置の入れ替えと不要なスペースの削除ではできると思うのですが、スペースの削除の方がうまくいかず。
結局replaceを使って不要な部分を削除してから新たに通貨記号を先頭に付ける形に変更しました。
参考
- 売り切れたバリエーションを非表示にする · Shopify ヘルプセンター
テーマに出力されるJSONの取得方法の参考に - Number.prototype.toLocaleString() – JavaScript | MDN
- Intl.NumberFormat.prototype.format() – JavaScript | MDNbr>こちらの方がフォーマットを自由に変更できる(通貨記号の位置変更など)
結び
当記事のコードには含んでいませんが、オプションが存在する場合はオプション変更に連動して価格も変化させる必要があります。
Shopifyで価格を表示するサンプルコードは多少目にしますが、この点に触れずJavaScriptも記載していない場合は、実際にはあまり使えないコードである可能性が高いように思います。
もちろんオプションがない前提のコードであることを明記していればよいのですが、割と書いておらず、その記事を見て簡単だという認識を持つと痛い目をみるかもしれません。
なお、テーマ内に通貨変換用の仕組みを持っているテーマはその仕組みを流用できると手間がかかりません。
流用できない場合は当記事のように自作するか、何らかのライブラリを読み込ませて使うか、アプリを探すかになります。
0人がこの記事を評価
役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。
連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。