상현
개발 덕후

대한민국 원 화폐단위 커스텀하기 (feat: i18next)

( 업데이트: )

i18next에는 formatting이 가능하다. Formatting – i18next documentation
포맷팅에 관한 자세한 내용은 공식문서를 살펴보면 좋을 것이다.

Javascript 기본 Intl.NumberFormat() 함수로는 1,000 원을 표현할 수 없다.

굳이 왜 Intl.NumberFormat()을 말하냐면 i18next의 currency 포맷팅이 Intl.NumberFormat으로 한다.

화폐단위를 포맷팅하게 되면

// {{상품_가격}}: {{상품_가격, price}}
t('{{prcie}}', {
    상품_가격: 1000,
    formatParams: {
        상품_가격: {
            currency: 'USD',
            currencyDisplay: 'name'
        }
    }
})

// 결과값 1,000 미국 달러
Code language: TypeScript (typescript)

이렇게 나오게된다. 하지만 우리는 미국 달러없이 달러라고 나오기를 원하고있다.

  • 미국 달러
  • 캐나다 달러

이런식으로 여러 나라를 동시에 표현할때면 맞겠지만 우리 서비스에는 미국 달러만 사용해서 달러라 표기해도 문제가 없다할때 달러라고 표기해야한다.

코드로만 표기한다면 그냥 reaplceAll해서 제거하면 되지만 우리는 번역 툴들을 사용할것이고 gettext i18next와 같은 표준을 사용해서 i18n을 호환되도록 만들것이다.

i18next에 custom fomatter를 추가해서 나라 명칭이 나온다면 제거하자

i18n.services.formatter?.add('currency', (value, lng, options) => {
    const overrideOptions = { ...options }
    // 기본값을 currency로 설정한다.
    if (!overrideOptions?.style) {
      overrideOptions.style = 'currency'
    }
    
    // 대한민국 통화 커스텀 포맷터
    // Javascript의 기본 Intl.NumberFormat에서 name의 값은 `대한민국 원`으로만 지원한다.
    // 하지만우리는 `1,000 원`을 원한다.
    // 모든 나라 화폐에 대해서 동일하게 화페 단위만 가져올 것이다.
    // - 대한민국 원
    // - 미국 달러
    // - 유로
    // - 일본 엔화
    if (
      overrideOptions?.removeCountry &&
      overrideOptions?.currencyDisplay === 'name'
    ) {
      const getCurrencyName = new Intl.NumberFormat(
        lng,
        overrideOptions
      ).format(value)
      const result = getCurrencyName.split(' ')
      // 가격제거
      const price = result.shift()

      // 기본 template
      const template = overrideOptions?.template || '[[amount]] [[currency]]'
      return template
        .replace('[[amount]]', String(price))
        .replace('[[currency]]', currency.slice(-1)[0])
    }
})Code language: TypeScript (typescript)

이제 i18next에서 기본적으로 넣어둔 currency에 대한 포맷팅을 덮어씌우게된다.

i18next에서 사용하기

const price = 234567
t('{{상품_가격}}', {
  상품_가격: price,
  formatParams: {
    상품_가격: {
      style: 'currency',
      currency: 'EUR',
      currencyDisplay: 'name',
      removeCountry: true, // custom 옵션
    }
  }
})Code language: TypeScript (typescript)