https://hyunki99.tistory.com/124
[Next.js] Next 15 국제화라이브러리 비교 + 적용하기 (i18n, next-intl)
요즘의 모던하고 글로벌한 웹에는 국제화(i18n)와 지역화(i10n)라는 개념이 등장합니다.쉽게 정리하면 다음과 같습니다.✅ 국제화(i18n, Internationalization): → 다국어 지원을 위해 코드 구조를 준비
hyunki99.tistory.com
지난 시간에 next-intl 라이브러리를 사용해서
다국어 지원을 구현했습니다.
이제 더 중요한 숙제가 남았는데요, 바로 다국어 메시지 관리입니다.
프로젝트의 규모가 커지고 지원하는 언어가 늘어나면
다국어 메시지를 관리하기 복잡해집니다.
코드를 수정할 때마다 각각의 언어 파일의 Json을 찾아 수정하고
반복하면 번거롭겠죠? 이는 개발자가 실수할 확률도 높습니다.
개발팀 내부, 외부에서 다국어 메시지를 관리하고 공유할 수 있는
문서가 있으면 의사소통 비용이 줄고 생산성이 좋아질 것 같다는 생각에
구글 스프레드시트를 활용하기로 했습니다. 😀
📝 데이터 설계 & 작업 흐름
⦁JSON 데이터 (원하는 데이터)
// messages/en.json
{
"LoginPage": {
"login": "Log in",
"logout": "Log out",
"placeholder": {
"account": "Account",
"password": "Password",
"referralCode": "Referral Code (6 digits)"
}
},
}
next-intl의 메시지 파일입니다. placeholder는 중첩된 객체구조입니다.
선택적으로 활용하면 메시지를 체계적인 구조로 사용할 수 있습니다. (더 복잡해지지 않도록 주의하세요)
⦁스프레드 시트
시트로 표현하면 위와 같습니다. 중첩된 객체는 . 으로 구분합니다.
필터같은 엑셀의 데이터 관련 부가 기능을 사용할 수 있는 장점도 있습니다.
⦁작업 흐름
이제 저희가 원하는 작업 흐름은 다음과 같습니다.
1. 다국어 메시지를 스프레드시트에 작성한다.
2. 포맷팅 함수를 동작시켜 원하는 형식의 json을 얻는다.
3. 복사 후 messages에 편리하게 붙여넣고 배포한다.
3번 같은 경우는 프로젝트 환경에 따라 많이 달라집니다.
S3에 json을 업데이트하는 방식도 있고 스프레드시트의 Api를 활용해 배포하는 방법도 있습니다.
저는 간단하게 시트에서 json만 추출해서 메시지에 바로 복사 붙여넣기를 할 수 있도록 구현했습니다. 😀 (반자동입니다)
📝 Apps Script 활용 Json 추출
⦁시트 상단 확장 프로그램 -> Apps Script
간단한 기능 때문에 Node 프로젝트를 하나 생성해야 하나 고민했는데,
시트 확장 프로그램에 신기하게 함수를 만들 수 있는 기능이 있더라고요
바로 사용해 봤습니다.
⦁소스코드
function generateTranslationsJson() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const data = sheet.getDataRange().getValues();
// 첫 번째 행은 헤더이므로 두 번째 행부터 시작
const translationsEn = {};
const translationsJp = {};
// 데이터를 순회하며 en과 jp 값을 각각 분리
for (let i = 1; i < data.length; i++) {
const [section, key, en, jp] = data[i];
// section이 '.'을 포함하면 중첩된 구조로 처리
const sectionKeys = section.split('.');
let currentEn = translationsEn;
let currentJp = translationsJp;
// sectionKeys를 순회하며 중첩된 객체를 만듦
sectionKeys.forEach((keyPart, index) => {
if (!currentEn[keyPart]) {
currentEn[keyPart] = index === sectionKeys.length - 1 ? {} : {};
currentJp[keyPart] = index === sectionKeys.length - 1 ? {} : {};
}
if (index === sectionKeys.length - 1) {
// 마지막 부분이라면 값을 넣어줌
currentEn[keyPart][key] = en;
currentJp[keyPart][key] = jp;
} else {
// 중간 단계는 객체를 계속 내려가며 만듦
currentEn = currentEn[keyPart];
currentJp = currentJp[keyPart];
}
});
}
// 결과를 JSON 형식으로 출력
const jsonEn = JSON.stringify(translationsEn, null, 2);
const jsonJp = JSON.stringify(translationsJp, null, 2);
// 잘못된 "" 두 번 문제를 해결하기 위한 추가 처리
const correctedJsonEn = jsonEn.replace(/""/g, '"');
const correctedJsonJp = jsonJp.replace(/""/g, '"');
Logger.log("English JSON:\n" + correctedJsonEn);
Logger.log("Japanese JSON:\n" + correctedJsonJp);
// 예시로 스프레드시트에 결과를 붙여넣기 (옵션)
const resultSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Results');
if (!resultSheet) {
resultSheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet('Results');
}
resultSheet.getRange(1, 1).setValue("English JSON:");
resultSheet.getRange(2, 1).setValue(correctedJsonEn);
resultSheet.getRange(10, 1).setValue("Japanese JSON:");
resultSheet.getRange(11, 1).setValue(correctedJsonJp);
}
⦁결과
프로젝트 이동할 필요 없이 간단하게 원하는 언어의 messages Json이 잘 추출 되었습니다. 🥳
프로젝트가 커진다면 namespace 칼럼을 시트로 구분하는 것도 좋은 방법일 것 같습니다.
여러분은 다국어의 Key값을 어떻게 구분하고 관리하는지 댓글로 알려주세요 !
참고 문헌 :
'Front-End > Next' 카테고리의 다른 글
[Next.js] Next 15 국제화라이브러리 비교 + 적용하기 (i18n, next-intl) (1) | 2025.02.24 |
---|---|
[Next.js] 넥스트 빌드파일 html id="__next_error__" 해결방법 (useSearchParams) (0) | 2025.01.21 |
[Next.js] TypeError: jsxDEV is not a function 해결 방법 (캐시 에러) (3) | 2024.10.07 |