๐Ÿ—‚ WIL/๐Ÿ“ Etc

๐Ÿคจ lingui

nalong 2024. 11. 3. 22:53

์ด๋ฒˆ์— ํšŒ์‚ฌ์—์„œ https://lingui.dev/introduction ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ˜„์žฌ ๋‹ค๊ตญ์–ด ์ž‘์—…์ด ํ•„์š”ํ•œ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•˜๋Š” ์ž‘์—…์„ ์ง„ํ–‰ ์ค‘์ธ๋ฐ, ๋‚˜๋„ ์ž ์‹œ ์ž‘์—…์„ ํ•จ๊ป˜ ์ง„ํ–‰ํ•˜๊ฒŒ ๋˜๋ฉด์„œ ์•Œ๊ฒŒ ๋œ lingui์— ๋Œ€ํ•ด ๊ฐ„๋‹จํ•˜๊ฒŒ ์ •๋ฆฌํ•ด ๋ณด์•˜๋‹ค.

1. Lingui ์ดˆ๊ธฐ ์„ค์ •

๋จผ์ € Lingui CLI์™€ ํ•„์š”ํ•œ ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜๊ฐ€ ํ•„์š”ํ•œ๋ฐ, @lingui/cli๋Š” CLI ๋„๊ตฌ๋กœ ๋ฉ”์‹œ์ง€ ์ถ”์ถœ ๋ฐ ๋ฒˆ์—ญ ๊ด€๋ฆฌ๋ฅผ ๋•๊ณ , @lingui/macro๋Š” ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•˜์—ฌ ๋ฒˆ์—ญ์ด ํ•„์š”ํ•œ ํ…์ŠคํŠธ๋ฅผ ์ธ์‹ํ•˜๊ณ , @lingui/react๋Š” React์—์„œ ์‚ฌ์šฉํ•  ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

npm install @lingui/cli @lingui/macro @lingui/react

๊ทธ๋ฆฌ๊ณ  lingui.config.js๋ฅผ ์ƒ์„ฑํ•ด์„œ locales ๋ฐฐ์—ด์— ๋‹ค๊ตญ์–ด ์ง€์›์„ ์›ํ•˜๋Š” ์–ธ์–ด ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ , sourceLocale์—๋Š” ๊ธฐ๋ณธ ์–ธ์–ด ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค.

module.exports = {
  // ์ŠคํŽ˜์ธ์–ด๋ฅผ ์ง€์›ํ•œ๋‹ค๊ณ  ๊ฐ€์ •
  locales: ["es"],
  sourceLocale: "ko",
  format: "po",  
  catalogs: [{
    path: "locales/{locale}/messages",
    include: ["src"],
  }],
};

2. ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ๋งคํฌ๋กœ๋“ค

๐Ÿ’— JS ๋งคํฌ๋กœ

โœจtโœจ
๊ฐ€์žฅ ๊ธฐ๋ณธ ๋งคํฌ๋กœ! ICU ๋ฉ”์‹œ์ง€ ํ˜•์‹์˜ ๋ฌธ์ž์—ด์„ ์ƒ์„ฑํ•˜๋ฉฐ, ํƒœ๊ทธ ๋œ ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด๋กœ ๋ณ€ํ™˜๋œ๋‹ค.

import { t } from "@lingui/macro";
const message = t`Hello World`;

//// ๋ณ€ํ™˜๋œ ์ฝ”๋“œ ↓ ↓ ↓ ↓ ↓ ↓

import { i18n } from "@lingui/core";
const message = i18n._(
  /*i18n*/ {
    id: "mY42CM",
    message: "Hello World",
  }
);

๋ณ€์ˆ˜์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

import { t } from "@lingui/macro";
const message = t`My name is ${name}`;

//// ๋ณ€ํ™˜๋œ ์ฝ”๋“œ ↓ ↓ ↓ ↓ ↓ ↓

import { i18n } from "@lingui/core";
const message = i18n._(
  /*i18n*/ {
    id: "mVmaLu",
    message: "My name is {name}",
    values: { name },
  }
);

๋‹จ์ˆœ ๋ณ€์ˆ˜๋ฅผ ์ œ์™ธํ•˜๊ณ ๋„ ์—ฌ๋Ÿฌ ํ‘œํ˜„์‹๋“ค์ด ํ…œํ”Œ๋ฆฟ ๋ฆฌํ„ฐ๋Ÿด์— ํฌํ•จํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ด๋Ÿฐ ๊ฒฝ์šฐ ํ‘œํ˜„์‹์€ ์ˆซ์ž ์ธ๋ฑ์Šค๋กœ ์ฐธ์กฐ๋œ๋‹ค.

import { t } from "@lingui/macro";
const message = t`Today is ${new Date()}`;

// ๋ณ€ํ™˜๋œ ์ฝ”๋“œ
import { i18n } from "@lingui/core";
const message = i18n._(
  /*i18n*/ {
    id: "2aJT27",
    message: "Today is {0}",
    values: { 0: new Date() },
  }
);

๋ฉ”์‹œ์ง€ ์„ค๋ช…์ž๋ฅผ ํ•จ๊ป˜ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

import { t } from "@lingui/macro";
const message = t({
  id: "msg.hello",
  comment: "Greetings at the homepage",
  message: `Hello ${name}`,
});

// ๋ณ€ํ™˜๋œ ์ฝ”๋“œ
import { i18n } from "@lingui/core";
const message = i18n._(
  /*i18n*/ {
    id: "msg.hello",
    comment: "Greetings at the homepage",
    message: "Hello {name}",
    values: { name },
  }
);

โœจpluralโœจ
๋ณต์ˆ˜ํ˜• ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.

import { plural } from "@lingui/macro";
const message = plural(count, {
  one: "# Book",
  other: "# Books",
});

// ↓ ↓ ↓ ↓ ↓ ↓

import { i18n } from "@lingui/core";
const message = i18n._(
  /*i18n*/ {
    id: "V/M0Vc",
    message: "{count, plural, one {# Book} other {# Books}}",
    values: { count },
  }
);

โœจselectOrdinalโœจ
์ˆœ์„œ๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.

import { selectOrdinal } from "@lingui/macro";
const message = selectOrdinal(count, {
  one: "#st",
  two: "#nd",
  few: "#rd",
  other: "#th",
});

// ↓ ↓ ↓ ↓ ↓ ↓

import { i18n } from "@lingui/core";
const message = i18n._(
  /*i18n*/ {
    id: "V8xI3w",
    message: "{count, selectOrdinal, one {#st} two {#nd} few {#rd} other {#th}}",
    values: { count },
  }
);

โœจselectโœจ
์กฐ๊ฑด์— ๋”ฐ๋ผ ๋ฉ”์‹œ์ง€๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉ๋œ๋‹ค.

import { select } from "@lingui/macro";
const message = select(gender, {
  male: "he",
  female: "she",
  other: "they",
});

// ↓ ↓ ↓ ↓ ↓ ↓

import { i18n } from "@lingui/core";

const message = i18n._(
  /*i18n*/ {
    id: "VRptzI",
    message: "{gender, select, male {he} female {she} other {they}}",
    values: { gender },
  }
);

โœจdefineMessage or msgโœจ
๋‚˜์ค‘์— ์‚ฌ์šฉํ•  ๋ฉ”์‹œ์ง€๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ฃผ๋Š”๋ฐ, ์ง€์—ฐ ๋ฒˆ์—ญ์— ์ฃผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

import { defineMessage } from "@lingui/macro";
const message = defineMessage`Hello World`;

// ↓ ↓ ↓ ↓ ↓ ↓

const message = /*i18n*/ {
  id: "mY42CM",
  message: "Hello World",
};

๐Ÿ’— JSX ๋งคํฌ๋กœ

โœจTransโœจ
์ •์  ๋ฉ”์‹œ์ง€, ๋ณ€์ˆ˜๋ฅผ ํฌํ•จํ•œ ๋ฉ”์‹œ์ง€, ๊ทธ๋ฆฌ๊ณ  ์ธ๋ผ์ธ ๋งˆํฌ์—…์ด ์žˆ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.

id: ์‚ฌ์šฉ์ž ์ง€์ • ๋ฉ”์‹œ์ง€ ID
comment: ๋ฒˆ์—ญ๊ฐ€๋ฅผ ์œ„ํ•œ ์ฃผ์„
context: ๋™์ผํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋‹ค๋ฅธ ID๋กœ ์ถ”์ถœ
import { Trans } from "@lingui/macro";
<Trans id="message.attachment_saved">Attachment {name} saved.</Trans>;

//์‚ฌ์šฉ์ž ์ง€์ • ๋ฉ”์‹œ์ง€ ID ↓ ↓ ↓ ↓ ↓ ↓

import { Trans } from "@lingui/react";
<Trans id="message.attachment_saved" message="Attachment {name} saved." />;
import { Trans } from "@lingui/macro";
<Trans context="direction">right</Trans>;
<Trans context="correctness">right</Trans>;

// context ์‚ฌ์šฉ์‹œ ๋‹ค๋ฅธ ์•„์ด๋””๋ฅผ ๋ถ€์—ฌํ•จ ↓ ↓ ↓ ↓ ↓ ↓

import { Trans } from "@lingui/react";
<Trans id={"d1wX4r"} message="right" />;
<Trans id={"16eaSK"} message="right" />;
import { Trans } from "@lingui/macro";

<Trans>
  Read the <a href="/docs">docs</a>.
</Trans>;

// ↓ ↓ ↓ ↓ ↓ ↓

import { Trans } from "@lingui/macro";
<Trans id={"mk8bSG"} message="Read the <0>docs</0>." components={{ 0: <a href="/docs" /> }} />;

์ปดํฌ๋„ŒํŠธ์™€ HTML ํƒœ๊ทธ๋Š” ๋”๋ฏธ ์ธ๋ฑ์Šค ํƒœ๊ทธ(<0></0>)๋กœ ๋Œ€์ฒด๋œ๋‹ค.

  • ์‚ฌ์šฉ์ž ์ •์˜ React ์ปดํฌ๋„ŒํŠธ์™€ ๊ธฐ๋ณธ HTML ํƒœ๊ทธ ๋ชจ๋‘ ์ง€์›.
  • ์ปดํฌ๋„ŒํŠธ์˜ props๋ฅผ ๋ณ€๊ฒฝํ•ด๋„ ๋ฒˆ์—ญ์ด ๊นจ์ง€์ง€ ์•Š์Œ.
  • ๋ฉ”์‹œ์ง€๊ฐ€ ์ „์ฒด ๋ฌธ์žฅ์œผ๋กœ ์ถ”์ถœ๋œ๋‹ค.

๐Ÿšจ๐Ÿค”๐Ÿšจ๐Ÿง ์ธ๋ฑ์Šค ํƒœํฌ๋ž€....?๐Ÿšจ๐Ÿค”๐Ÿšจ๐Ÿง

<p>
  <Trans>
    See all <a href="/unread">unread messages</a>
    {" or "}
    <a onClick={markAsRead}>mark them</a> as read.
  </Trans>
</p>

๋งŒ์•ฝ ์œ„์˜ ์ฝ”๋“œ๋ฅผ extract ๋ช…๋ น์–ด๋ฅผ ๋Œ๋ ค ์ถ”์ถœํ•˜์ž๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด html ํƒœ๊ทธ๋“ค์€ ์ธ๋ฑ์Šค ํƒœ๊ทธ๋กœ ๋ณ€๊ฒฝ๋˜์–ด์„œ ์ €์žฅ๋œ๋‹ค.

"See all <0>unread messages</0> or <1>mark them</1> as read."

๋‚˜๋Š” ์ธ๋ฑ์Šค ํƒœ๊ทธ( <0>, <1>)๋ฅผ ๊ณ„์† ๋ฒˆ์—ญ ๋ฌธ์žฅ๊ณผ ์—ฎ์–ด์„œ ์ƒ๊ฐ์„ ํ•ด์„œ ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ์–ด๋ ค์› ๋Š”๋ฐ ๐Ÿฅฒ, ๋‹จ์ˆœํžˆ ์ƒ๊ฐํ•ด์„œ ํƒœ๊ทธ/์ปดํฌ๋„ŒํŠธ ํ‘œ์‹œํ•˜๋Š” ํƒœ๊ทธ.. ๋ฌธ๋ฒ•์œผ๋กœ ์ƒ๊ฐํ•˜๋‹ˆ ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ์‰ฌ์›Œ์กŒ๋‹ค.

 

์ธ๋ฑ์Šค ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋กœ ์ฒซ ๋ฒˆ์งธ ํƒœ๊ทธ๋ฅผ ๋‹จ์ˆœํ•˜๊ฒŒ ๊ด€๋ฆฌ ์œ„ํ•จ์ธ๋ฐ, ๋ฒˆ์—ญ ๊ณผ์ •์—์„œ HTML์ด๋‚˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ํฌํ•จํ•˜๋ฉด ๋ฒˆ์—ญ๊ฐ€๋“ค์ด ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ๊ธฐ์—, ํƒœ๊ทธ๋‚˜ ์ปดํฌ๋„ŒํŠธ๋Š” ์ˆซ์ž ์ธ๋ฑ์Šค๋กœ ํ‘œ์‹œํ•˜์—ฌ ๊ด€๋ฆฌ๊ฐ€ ์‰ฝ๋„๋ก ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.
๋‘ ๋ฒˆ์งธ๋กœ๋Š” ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‹œ ๋ฒˆ์—ญ์— ์˜ํ–ฅ์ด ์—†๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„œ์ด๋‹ค. ์ธ๋ฑ์Šค ํƒœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์˜€๊ธฐ์— ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ์˜ className์ด๋‚˜ onClick ๊ฐ™์€ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๋”๋ผ๋„ ๋ฒˆ์—ญ ๋ฉ”์‹œ์ง€์—๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค. ๋ฒˆ์—ญ ๋ฉ”์‹œ์ง€๋Š” ์˜ค๋กœ์ง€ ์ธ๋ฑ์Šค๋กœ ํƒœ๊ทธ ์œ„์น˜๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ฉ”์‹œ์ง€๋ฅผ ์žฌ๋ฒˆ์—ญํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ํ•œ๋‹ค.

 

๊ทธ๋Ÿผ ์ปดํฌ๋„ŒํŠธ/ํƒœ๊ทธ๊ฐ€ ์žˆ๋Š” ๋ฒˆ์—ญ ๋ฉ”์‹œ์ง€์˜ ๋™์ž‘ ๋ฐฉ์‹์€ ์œ„์˜ ์ถ”์ถœ๋œ ๋ฉ”์‹œ์ง€์—์„œ <0>๊ณผ <1>์€ ๊ฐ๊ฐ <a href="/unread">์™€ <a onClick={markAsRead}>์— ๋Œ€์‘๋˜๊ณ , Trans ๋งคํฌ๋กœ๊ฐ€ ์ด ๋ฉ”์‹œ์ง€๋ฅผ ๋ Œ๋”๋ง ํ•  ๋•Œ, ์ธ๋ฑ์Šค ํƒœ๊ทธ๋Š” JSX๋กœ ๋˜๋Œ์•„๊ฐ€๋ฉด์„œ ์›๋ž˜ ์œ„์น˜์— ๋งž์ถฐ ์ปดํฌ๋„ŒํŠธ์™€ ์†์„ฑ๋“ค์ด ๋ Œ๋”๋ง ๋œ๋‹ค.

 

โœจPluralโœจ
๋ณต์ˆ˜ํ˜• ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜์ด ํ•„์š”ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.

import { Plural } from "@lingui/macro";
<Plural value={numBooks} one="Book" other="Books" />;

// ↓ ↓ ↓ ↓ ↓ ↓

import { Trans } from "@lingui/react";
<Trans id={"is7n96"} message="{numBooks, plural, one {Book} other {Books}}" values={{ numBooks }} />;

#์€ ์ˆซ์ž ํ˜•์‹์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

import { Plural } from "@lingui/macro";

<Plural
  value={count}
  one="You and # other guest arrived"
  // when value >= 3
  other="You and # other guests arrived"
/>;

๋งŒ์•ฝ id, context, ๋˜๋Š” comment๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด <Trans> ๋งคํฌ๋กœ ๋‚ด๋ถ€์—์„œ <Plural>์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

 

โœจSelectOrdinalโœจ
ํŠน์ • ์œ„์น˜๋‚˜ ์ˆœ์„œ๋ฅผ ๋‚˜ํƒ€๋‚ผ ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.

import { SelectOrdinal } from "@lingui/macro";

// count == 1 -> 1st
// count == 2 -> 2nd
// count == 3 -> 3rd
// count == 4 -> 4th
<SelectOrdinal value={count} one="#st" two="#nd" few="#rd" other="#th" />;

โœจSelectโœจ
๊ฐ’์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ฌธ์žฅ์„ ํ‘œ์‹œํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.

 import { Select } from "@lingui/macro";

// gender == "female"      -> Her book
// gender == "male"        -> His book
// gender == "non-binary"  -> Their book
<Select value={gender} _male="His book" _female="Her book" other="Their book" />;

other๋ฅผ ์ œ์™ธํ•œ ์„ ํƒ ํ•ญ๋ชฉ๋“ค์€ ๋ฐ‘์ค„(_)๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค. ์˜ˆ: _male, _female.

3. React์—์„œ Lingui ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉํ•˜๊ธฐ

๐Ÿ”ฅ Trans๋กœ ๊ฐ์‹ธ๊ธฐ
React ์ปดํฌ๋„ŒํŠธ์—์„œ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ฒˆ์—ญ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

import { Trans } from "@lingui/macro";

function render() {
  return (
    <>
      <h1>
        <Trans>LinguiJS example</Trans>
      </h1>
      <p>
        <Trans>
          Hello <a href="/profile">{name}</a>.
        </Trans>
      </p>
    </>
  );
}

๐Ÿ”ฅ Trans ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๋„ ๋ฐœ์ƒํ•˜๋Š”๋ฐ, ์ด๋•Œ t ๋งคํฌ๋กœ ์‚ฌ์šฉ์ด ํ•„์š”ํ•˜๋‹ค.

โœ… Trans ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ

1. ์ปดํฌ๋„ŒํŠธ ์™ธ๋ถ€์—์„œ ํ…์ŠคํŠธ ๋ฒˆ์—ญ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ

2. ์š”์†Œ์˜ ์†์„ฑ ๊ด€๋ จํ•œ ํ…์ŠคํŠธ ๋ฒˆ์—ญ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ

t, plural, select, selectOrdinal ๋งคํฌ๋กœ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ธ€๋กœ๋ฒŒ i18n ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ์— ๋Œ€๋ถ€๋ถ„์˜ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ ํ™˜๊ฒฝ์—์„œ ์ž˜ ๋™์ž‘ํ•˜์ง€๋งŒ, ์„œ๋ฒ„์‚ฌ์ด๋“œ ๋ Œ๋”๋ง(SSR)๊ณผ ๊ฐ™์€ ํŠน์ˆ˜ํ•œ ์ƒํ™ฉ์—์„œ๋Š” ํŠน์ • ์ธ์Šคํ„ด์Šค๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹๋‹ค๊ณ  ํ•œ๋‹ค.

import { msg } from "@lingui/macro";
import { I18n } from "@lingui/core";

export function component () {

  const { i18n } = useLingui();

  alert(t(i18n)`ํ† ๋งˆํ† `);

  return (
    <div>...</div>
  )
}

๐Ÿ”ฅ ๋ณ€์ˆ˜ ๊ฐ’์— ๋”ฐ๋ฅธ ๋ฉ”์‹œ์ง€ ๋™์  ์„ ํƒ

๋ณ€์ˆ˜์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋ฉ”์‹œ์ง€๋ฅผ ์„ ํƒํ•ด์•ผ ํ•  ๋•Œ๋„ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, API์—์„œ ๋ฐ›์€ ์ˆซ์ž "status" ์ฝ”๋“œ๊ฐ€ ์žˆ์„ ๋•Œ, ์ด ์ฝ”๋“œ์— ๋”ฐ๋ผ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ด์•ผ ํ•œ๋‹ค๋ฉด "status"์˜ ๊ฐ€๋Šฅํ•œ ๊ฐ’๋“ค์„ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด, ๋ฒˆ์—ญ์„ ์ง€์—ฐ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์œผ๋กœ ๋ Œ๋”๋ง ํ•  ์ˆ˜ ์žˆ๋‹ค.

import { msg } from "@lingui/macro";
import { useLingui } from "@lingui/react";

const statusMessages = {
  ["STATUS_OPEN"]: msg`Open`,
  ["STATUS_CLOSED"]: msg`Closed`,
  ["STATUS_CANCELLED"]: msg`Cancelled`,
  ["STATUS_COMPLETED"]: msg`Completed`,
};

export default function StatusDisplay({ statusCode }) {
  const { _ } = useLingui();
  return <div>{_(statusMessages[statusCode])}</div>;
}

 

++++++ ๋А๋‚€ ์  ๊ทธ๋ฆฌ๊ณ  ๊ฒฐ๋ก  ++++++

ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ๋งคํฌ๋กœ๋“ค๊ณผ ๋ฆฌ์•กํŠธ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ๋“ค๋งŒ ๊ฐ„๋‹จํžˆ ์ •๋ฆฌํ•ด ๋ณด์•˜๋Š”๋ฐ, ์ž˜ ๋ฒˆ์—ญ์ด ๋˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ฌธ๋ฒ•์— ๋งž๊ฒŒ ๋‹ค์–‘ํ•œ ๋งคํฌ๋กœ๋ฅผ ์ž˜ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๋А๊ผˆ๋‹ค. ํ˜„์žฌ ํšŒ์‚ฌ์—์„œ๋Š” ๋‹ค๊ตญ์–ด ํ”„๋กœ์ ํŠธ๊ฐ€ ๊ธ‰ํ•˜๊ฒŒ ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜์–ด์„œ ๋ฌธ๋ฒ•์— ๋งž๋Š” ์„ธ๋ฐ€ํ•œ ๋งคํฌ๋กœ ์‚ฌ์šฉ ๋Œ€์‹  ์ผ๋‹จ ๋ฒˆ์—ญ์ด ๋˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์— ์ง‘์ค‘์ด ๋˜์–ด ์žˆ๋Š” ์ƒํ™ฉ์ด๋ผ.... ์–ด์ƒ‰ํ•œ ๋ถ€๋ถ„๋“ค์ด ๋งŽ์ด ์žˆ์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋˜๋Š”๋ฐ.. ๊ฒฐ๋ก  ->  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž˜ ์‚ฌ์šฉํ•˜๊ธฐ๋ž€ ์‰ฝ์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™๋‹ค. ๐Ÿฅฒ