EJS
Lingo.dev CLI를 이용한 EJS 템플릿 AI 번역
EJS란 무엇인가요?
EJS(Embedded JavaScript)는 일반 JavaScript를 사용하여 HTML 마크업을 생성할 수 있는 간단한 템플릿 언어입니다. 주로 Node.js 애플리케이션에서 서버 사이드 렌더링에 사용됩니다.
Lingo.dev CLI란 무엇인가요?
Lingo.dev CLI는 AI를 사용하여 앱과 콘텐츠를 번역하기 위한 무료 오픈소스 CLI입니다. 기존 파이프라인과 통합하면서 전통적인 번역 관리 소프트웨어를 대체하도록 설계되었습니다.
자세한 내용은 개요를 참조하세요.
이 가이드에 대하여
이 가이드는 Lingo.dev CLI를 사용하여 EJS 템플릿을 번역하는 방법을 설명합니다.
다음 내용을 배우게 됩니다:
- 처음부터 프로젝트 생성하기
- 번역 파이프라인 구성하기
- AI로 번역 생성하기
사전 요구사항
Lingo.dev CLI를 사용하려면 Node.js v18 이상이 설치되어 있어야 합니다:
❯ node -v
v22.17.0
1단계. 프로젝트 설정하기
프로젝트 디렉토리에 i18n.json 파일을 생성합니다:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
이 파일은 번역할 언어와 파일 시스템에서 지역화 가능한 콘텐츠가 존재하는 위치를 포함하여 번역 파이프라인의 동작을 정의합니다.
사용 가능한 속성에 대해 자세히 알아보려면 i18n.json을 참조하세요.
2단계. 소스 로케일 구성하기
_소스 로케일_은 콘텐츠가 원래 작성된 언어와 지역입니다. 소스 로케일을 구성하려면 i18n.json 파일에서 locale.source 속성을 설정하세요:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
소스 로케일은 BCP 47 언어 태그로 제공되어야 합니다.
Lingo.dev CLI가 지원하는 로케일 코드의 전체 목록은 지원되는 로케일 코드를 참조하세요.
3단계. 대상 로케일 구성하기
_대상 로케일_은 콘텐츠를 번역하고자 하는 언어와 지역입니다. 대상 로케일을 구성하려면 i18n.json 파일에서 locale.targets 속성을 설정하세요:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {}
}
4단계. 소스 콘텐츠 생성하기
아직 생성하지 않았다면, 번역할 콘텐츠가 포함된 하나 이상의 EJS 템플릿 파일을 생성하세요. 이 파일들은 경로 어딘가에 소스 로케일이 포함된 위치에 있어야 합니다(예: en/과 같은 디렉토리 이름이나 messages.en.ejs와 같은 파일 이름의 일부로).
EJS 템플릿에서 번역 가능한 콘텐츠는 다음과 같습니다:
- HTML 요소 내의 텍스트 콘텐츠
- 속성 값(alt 텍스트, 제목, 레이블, 플레이스홀더, 버튼 값)
- JavaScript alert() 또는 기타 문자열 리터럴 내의 텍스트
EJS 템플릿 태그(<%= %>, <%- %>, <% %>)와 변수 이름은 번역 중에 보존됩니다.
예시:
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= pageTitle %></title>
</head>
<body>
<h1>다시 오신 것을 환영합니다!</h1>
<p>안녕하세요, <%= user.name %>님! <%= messageCount %>개의 새 메시지가 있습니다.</p>
<form action="/login" method="post">
<label for="username">사용자 이름:</label>
<input type="text" id="username" placeholder="사용자 이름 입력">
</form>
</body>
</html>
5단계. 버킷 생성하기
-
i18n.json파일에서buckets객체에"ejs"객체를 추가하세요:{ "$schema": "https://lingo.dev/schema/i18n.json", "version": "1.10", "locale": { "source": "en", "targets": ["es"] }, "buckets": { "ejs": {} } } -
"ejs"객체에서 하나 이상의include패턴 배열을 정의하세요:{ "$schema": "https://lingo.dev/schema/i18n.json", "version": "1.10", "locale": { "source": "en", "targets": ["es"] }, "buckets": { "ejs": { "include": ["./[locale]/example.ejs"] } } }이러한 패턴은 번역할 파일을 정의합니다.
패턴 자체는:
- 구성된 로케일의 플레이스홀더로
[locale]을 포함해야 합니다 - 파일 경로를 가리킬 수 있습니다(예:
"[locale]/config.ejs") - 와일드카드 플레이스홀더로 별표를 사용할 수 있습니다(예:
"[locale]/*.ejs")
재귀적 글로브 패턴(예:
**/*.ejs)은 지원되지 않습니다. - 구성된 로케일의 플레이스홀더로
6단계. LLM 구성하기
Lingo.dev CLI는 AI로 콘텐츠를 번역하기 위해 대규모 언어 모델(LLM)을 사용합니다. 이러한 모델 중 하나를 사용하려면 지원되는 제공업체의 API 키가 필요합니다.
가능한 빨리 시작하려면 매월 10,000 토큰의 무료 사용량을 제공하는 자체 호스팅 플랫폼인 Lingo.dev Engine을 사용하는 것이 좋습니다:
-
다음 명령어를 실행하세요:
npx lingo.dev@latest login이렇게 하면 기본 브라우저가 열리고 인증을 요청합니다.
-
안내에 따라 진행하세요.
7단계. 번역 생성하기
i18n.json 파일이 포함된 디렉토리에서 다음 명령어를 실행하세요:
npx lingo.dev@latest run
이 명령어는 다음을 수행합니다:
i18n.json파일을 읽습니다.- 번역이 필요한 파일을 찾습니다.
- 파일에서 번역 가능한 콘텐츠를 추출합니다.
- 구성된 LLM을 사용하여 추출된 콘텐츠를 번역합니다.
- 번역된 콘텐츠를 파일 시스템에 다시 작성합니다.
번역이 처음 생성될 때 i18n.lock 파일이 생성됩니다. 이 파일은 어떤 콘텐츠가 번역되었는지 추적하여 이후 실행 시 불필요한 재번역을 방지합니다.
예시
en/example.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= pageTitle %></title>
</head>
<body>
<% if (user) { %>
<h1>Welcome back!</h1>
<p>Hello, <%= user.name %>! You have <%= messageCount %> new messages.</p>
<% } else { %>
<h1>Please log in</h1>
<form action="/login" method="post">
<label for="username">Username:</label>
<input type="text" id="username" placeholder="Enter username">
<button type="submit">Sign In</button>
</form>
<% } %>
</body>
</html>
es/example.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= pageTitle %></title>
</head>
<body>
<% if (user) { %>
<h1>¡Bienvenido de nuevo!</h1>
<p>Hola, <%= user.name %>! Tienes <%= messageCount %> nuevos mensajes.</p>
<% } else { %>
<h1>Por favor, inicia sesión</h1>
<form action="/login" method="post">
<label for="username">Nombre de usuario:</label>
<input type="text" id="username" placeholder="Enter username">
<button type="submit">Iniciar sesión</button>
</form>
<% } %>
</body>
</html>
i18n.json
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.10",
"locale": {
"source": "en",
"targets": ["es"]
},
"buckets": {
"ejs": {
"include": ["./[locale]/example.ejs"]
}
}
}
i18n.lock
version: 1
checksums:
21b99a2aea148b309f95ec2c966d326c:
text_0: e4d2da607604b3fda41eef5e0dd35faa
text_1: 69eb28c44f7168b1df0455ad2a62588c
text_2: bff335b01588a8db802bd193c725ec11
text_3: 0744639a7ac440afe0d792ea79c54512
text_4: b4cc462fb3a00d2f60deefe548c10a33
text_5: d0fd310aef9cf3c5827f1db4b0c098a1
text_6: 85bb1f6fb66b5ab65a9c61469183236e
text_7: bdbc827b3d224e03394dfd56304500f2
text_8: 5e8497af456decf6cf716c0a23f1dbc2
text_9: d572e25ed81420669e65c03925da1001
text_10: 2cf6537fb69cdd2eb030e55bf4223b93
text_11: ec7b8f314fe9bc6591006707484ede61
text_12: c2460fb2a7887fdf2d68db2b553a4338
text_13: 3abe623951250bd24a9d7799415761ab
text_14: 988be328b82702586f2cd541858710fe
text_15: b2328773b0ef0699fd5791055c5cf9e2
text_16: 92acabd12cd9b63c825294c54fcbc806