문자 시트 i18n 또는 국제화를 사용하면문자 시트를 번역가 커뮤니티가 해당 언어로 번역할 수 있는 방식으로 디자인하여 Roll20의 모든 사용자가 해당 언어를 사용할 수 있도록 할 수 있습니다. 당신의 시트가 다른 언어로 번역되었고, 시트를 사용하는 사람의 계정 언어가 해당 언어로 설정되어 있다면, 해당 사용자를 위한 번역된 텍스트가 시트에 표시됩니다.
시트 디자인하기
i18n 서비스에 응답할 수 있도록시트설정은 매우 간단합니다. 특히 큰 기존 시트와 작업하는 경우 시간이 걸릴 수 있습니다. 시트를 번역할 수 있도록 하려면 2단계를 거쳐야 합니다. 첫 번째로, 번역된 텍스트를 포함하고자 하는 요소를 표시합니다. 두 번째로, 번역될 모든 문자열을 포함하는 번역 파일을 생성합니다. 이 파일은 번역 서비스인 Crowdin에 제공되며, 자원 봉사자들이 문자열마다 번역 작업을 수행합니다. 이렇게 하면 모든 다른 언어에 대해 동일한 번역 파일이 생성되며, 해당 언어가 Roll20에서 선택된 경우 사용됩니다.
다른 크기의 번역된 텍스트에 맞는 하나의 디자인을 만드는 것은 어려울 수 있으므로, "charsheet" 부모 요소에 클래스를 추가하여 개별 언어에 대한 별도의 CSS를 사용할 수 있습니다. 이 클래스는 "lang-[2자리 언어 코드]"입니다. 예를 들어, 영어의 경우 "lang-en" 또는 프랑스어의 경우 "lang-fr"입니다. 시트가 번역된 후에는, 해당 언어에 대한 새로운 텍스트가 현재 디자인에 맞지 않는 경우에만 해당 언어를 위해 특정 스타일을 변경할 수 있습니다.
1단계, 시트 포맷팅
모든 텍스트가 번역되길 원하는 요소에는 "data-i18n=[고유 키]" 속성을 추가해야합니다. 요소에 이미 있는 모든 텍스트를 유지하십시오. 완료 후 번역 파일을 생성하는 데 사용할 수 있습니다 (나중에 설명됨). 시트-i18n 코드가 개발에만 있는 동안에는 텍스트가 그대로 유지되는 것이 특히 중요합니다. 그렇지 않으면 시트-i18n이 메인에 적용될 때까지 시트가 메인 사이트에서 더 이상 작동하지 않습니다.i18n 번역의 작동 방식에 대한 추가 예제를 보려면 이미 i18n 텍스트로 서식이 지정된5th Edition OGL by Roll20시트를 확인하세요.
표준 텍스트
<div class="col"> <div class="row"> <span data-i18n="acrobatics-u">ACROBATICS <span>(Dex)</span></span> <input class="num" type="text" name="attr_npc_acrobatics" placeholder="0"> </div> <div class="row"> <span data-i18n="animal-handling-u">ANIMAL HANDLING</span> <input class="num" type="text" name="attr_npc_animal_handling" placeholder="0"> </div> <div class="row"> <span data-i18n="arcana-u">ARCANA</span> <input class="num" type="text" name="attr_npc_arcana" placeholder="0"> </div> <div class="row"> <span data-i18n="athletics-u">ATHLETICS</span> <input class="num" type="text" name="attr_npc_athletics" placeholder="0"> </div> <div class="row"> <span data-i18n="deception-u">DECEPTION</span> <input class="num" type="text" name="attr_npc_deception" placeholder="0"> </div> <div class="row"> <span data-i18n="history-u">HISTORY</span> <input class="num" type="text" name="attr_npc_history" placeholder="0"> </div> </div>
이 코드 블록의 모든 span에는 span에 포함된 텍스트를 참조하는 키가 있는 data-i18n 속성이 있음을 유의하십시오. 또한 span 내에 HTML이 있는 것에 유의하십시오. 이는 완전히 괜찮습니다. HTML은 Crowdin에서 표시되므로 HTML을 복사하여 번역에 쉽게 붙여넣을 수 있습니다. 번역 내에서 HTML은 괜찮지만 가능한 한 간단하게 유지하십시오. 번역자들은 주로 코드에 익숙하지 않을 수 있으며, 코드를 복사하는 데 문제가 발생할 수 있습니다. 모든 고유한 문자열에는 고유한 키가 있어야합니다. 이 텍스트는 모두 대문자이므로 각 키 끝에 -u를 사용하고 있음을 유의하십시오. 이는 이러한 단어가 시트의 나중에 나타나지만 일반적으로 대문자로 표시되는 이유입니다.
약어와 같은 경우 텍스트만으로는 번역자가 이해하지 못할 수있는 키에 추가적인 문맥을 추가해야하는 경우가 있습니다.
<div class="row"> <span data-i18n="components:-u">구성요소:</span> <input type="checkbox" name="attr_spellcomp_v" value="{{v=1}}" checked="checked"> <span data-i18n="spell-component-verbal">V</span> <input type="checkbox" name="attr_spellcomp_s" value="{{s=1}}" checked="checked"> <span data-i18n="spell-component-somatic">S</span> <input type="checkbox" name="attr_spellcomp_m" value="{{m=1}}" checked="checked"> <span data-i18n="spell-component-material">M</span> <input type="text" name="attr_spellcomp_materials" accept="Material" style="margin-left: 17px; width: 215px;" placeholder="ruby dust worth 50gp" data-i18n-place="ruby-dust-place"> </div>
V, S, M 텍스트에 대한 키를 확인하세요. 그렇지 않으면, 번역자는 "V"가 무엇을 의미하는지 알 수 없습니다. 이렇게 하면 번역자는 "Verbal"이라는 단어의 첫 글자로 "V"를 바꿀 수 있습니다.
요소 속성 텍스트
많은 경우에 속성 내부에 번역이 필요한 텍스트가 있습니다. 예를 들어, placeholder와 제목입니다. 이러한 속성 내부의 텍스트를 바꾸려면 "data-i18n-[attribute]='key'"를 사용하여 제공하는 키가 주어진 속성 내부의 텍스트를 대체해야 함을 파서에게 알려야 합니다. 예를 들어, placeholder 속성의 텍스트를 교체하는 경우:
<input name="attr_weapon_name" data-i18n-placeholder="weapon-name" placeholder="Hand Axe" />
지원되는 속성은 다음과 같습니다: 제목, 대체 텍스트, aria-label, 레이블, placeholder
변수 대체
한 가지 특별한 경우는 번역하지 않으려는 문자열 내에 텍스트가 있는 경우 특수 변수와 "data-i18n-vars" 속성을 사용할 수 있습니다.
<span data-i18n="var-test" data-i18n-vars="will not|be translated">이 텍스트 {{0}} {{1}}</span>
data-i18n-vars 속성 내의 텍스트는 "|" 문자로 분할되어 배열에 배치됩니다. 그런 다음 배열의 특정 행을 참조하기 위해 {{[index]}} 을 사용할 수 있습니다.
동적 키 대체
변경 가능한 키를 기반으로 번역을 가져와야 하는 상황이 있습니다. 예를 들어, "클래스 선택" 드롭다운 메뉴가 있고 사용자가 자신의 클래스를 선택할 수 있는 경우입니다. 이 목록에 표시되는 클래스 이름은 일반 도구를 사용하여 번역할 수 있습니다. 하지만, 선택 상자 안의 옵션 값은 번역할 수 없습니다. (이렇게 하면 언어를 변경하더라도 시트 데이터를 번역할 필요가 없습니다. 번역 시스템은 데이터 레이어가 아닌 프론트엔드에서만 작동합니다) 대신, 이 클래스 이름을 표시할 위치에 "data-i18n-dynamic" 속성을 가진 span을 표시합니다. 이렇게 하면 파서가 일반적으로 span에 표시되는 값을 키로 사용하여 번역을 가져올 수 있습니다.
// 이 부분은 변경할 필요가 없습니다 <select class="hiding" name="attr_class" style="width: 64px;"> <option value="Barbarian" data-i18n="barbarian">Bárbaro</option> <option value="Bard" data-i18n="bard">Bardo</option> <option value="Cleric" data-i18n="cleric">Clerigo</option> <option value="Druid" data-i18n="druid">Druida</option> </select>
<span data-i18n="class-options">Class Options</span> (<span name="attr_class" data-i18n-dynamic></span>)
{ "Barbarian":"Bárbaro", "Bard":"Bardo", "Cleric":"Clerigo", "Druid":"Druida" }
이제 위의 코드로, select 상자에서 "Bárbaro"를 선택하면 "Barbarian"이 attr_class에 저장됩니다. 그러나 시트가 새로 고쳐지고 name="attr_class"인 span에 "Barbarian"이 일반적으로 채워질 때, 대신 "Barbarian"이 번역 JSON을 참조하고 "Bárbaro"를 표시합니다.
주사위 굴리기
롤 쿼리의 텍스트는 캐릭터 시트 HTML에서 번역할 수 없지만,Sheet Worker Scripts및 속성을 사용하여 JavaScript에서 텍스트를 번역하고 롤 쿼리에 대체할 수 있습니다.
<script type="text/worker"> on("sheet:opened", function(eventInfo){ setAttrs({ bonusmacro: getTranslationByKey("ask-bonus") }); }); </script>
<span style="display: none" data-i18n="ask-bonus">보너스는 얼마인가요?</span> <button type='roll' value='[[d20 + ?{@{bonusmacro}|0}]]' ></button>
<span> 태그는 표시되지 않지만, 생성된 번역 파일에 "ask-bonus" 키가 포함됩니다. 스크립트는 "보너스매크로"라는 속성을 생성하고 값으로 "보너스는 무엇입니까?"를 할당하며, 롤 버튼은 그 값을 사용하여 "[[d20 + ?{보너스는 무엇입니까?|0}]]" 명령을 전송합니다. 시트가 다른 번역 파일이 활성화된 상태에서 열릴 경우, "보너스매크로"에 대한 새로운 번역 값으로 속성을 설정합니다. 이 기술은 개별 키를 대체하거나, 단일 속성을 사용하여 복잡한 쿼리를 저장하는 데 사용할 수 있으며, 시트 워커 스크립트는 필요에 따라 번역된 키를 쿼리 코드에 삽입합니다.
<script type="text/worker"> on("sheet:opened", function(eventInfo){ setAttrs({ rollquery: "?{" + getTranslationByKey("advantageordisadvantage") +"|" + getTranslationByKey("neither") + ",d20|" + getTranslationByKey("advantage") + ",2d20kh1[" + getTranslationByKey("withadvantage") + "]|" + getTranslationByKey("disadvantage") + ",2d20kl1[" + getTranslationByKey("withdisadvantage") + "]}", }); }); </script>
<span style="display: none" data-i18n="advantageordisadvantage">어드밴티지 또는 디스어드밴티지로 굴리고 계신가요?</span> <span style="display: none" data-i18n="neither">아무것도 아님</span> <span style="display: none" data-i18n="advantage">어드밴티지</span> <span style="display: none" data-i18n="withadvantage">어드밴티지와 함께</span> <span style="display: none" data-i18n="disadvantage">디스어드밴티지</span> <span style="display: none" data-i18n="withdisadvantage">디스어드밴티지와 함께</span> <button type='roll' value='[[@{rollquery}]]' ></button>
이 예제는 기본 번역 파일을 사용하여 다음과 같은 롤을 생성합니다.
[[?{어드밴티지 또는 디스어드밴티지로 굴리고 계신가요?|아무것도 아님,d20|어드밴티지,2d20kh1[어드밴티지와 함께]|디스어드밴티지,2d20kl1[디스어드밴티지와 함께]}]]
롤 템플릿
시트의 롤 템플릿 정의 내부의 정적 HTML은 동적 키를 포함한 모든 도구를 사용할 수 있습니다. 만약 시트의 롤 템플릿 정의 내에 있는 경우, 코드{{strength-key}}은 {{strength-key}}의 값에 해당하는 번역된 값을 제공합니다. 롤 함수 내에서 동적으로 번역된 값을 전송하려면 아래 도구를 사용하세요.
롤 템플릿을 사용하여 롤 함수 내에서 어떤 텍스트든지 "^{ [key] }"로 감싸서 번역 키로 표시할 수 있습니다. 이 텍스트는 해당 키와 연결된 번역 버전으로 대체될 것입니다. 이 단계는 캐릭터 시트 값이 교체된 후에 발생하므로, "^{ @{ability_key} }"는 ability_key = STRENGTH인 경우 "^{STRENGTH}"로 구문 분석되어 "STRENGTH"에 대한 번역 값이 표시됩니다. 이는 allprops() 함수에서 사용되는 키/값 쌍에 대해서도 작동합니다. 예를 들어: "{{^{TEXT}=@{content} }}"는 allprops() 함수 내에서 "TEXT"에 대한 번역 값으로 "{{key}}"를 가집니다.
목록 정렬
컨테이너에 항목 목록이 있고, 영어로 알파벳순으로 정렬된 경우, 다른 언어에서 순서를 변경하고 싶을 때 이 도구를 사용할 수 있습니다. 재정렬은 목록의 현재 서식을 모두 존중하므로, 목록이 여러 하위 컨테이너에 걸쳐 있는 경우에도 모든 것이 동일한 방식으로 서식이 유지됩니다.
컨테이너를 식별합니다. 모든 목록 항목은 컨테이너 내에 있어야 하며, 그렇지 않으면 무시됩니다:
data-i18n-list="list-key"
목록에서 개별 항목을 식별합니다. 이 항목들은 HTML 블록일 수 있습니다. 재정렬될 때 전체 블록이 이동됩니다.
data-i18n-list-item="item-key"
(선택 사항) 목록의 "시작" 순서는 HTML에서 위에서 아래로 읽힌다고 가정합니다. 순서가 다른 경우 항목을 수동으로 번호를 매겨 순서를 설정할 수 있습니다 (1부터 시작).
data-i18n-list-item-num="1"
(특수) 이 태그는 "사용"하지 않을 것이며, 포맷팅에 오류가 있는 경우에 생성됩니다. List Order 코드에 오류가 있는 경우 목록은 무시되고 이 태그가 오류가 있는 목록 컨테이너 요소에 생성됩니다. 예상과 다르게 목록이 재정렬되지 않는 경우 부모 요소에서 오류를 확인하세요.
data-i18n-error="오류 메시지"
번역 파일에 키를 추가하세요. 이는 원본 번역의 언어로 모든 항목 키의 쉼표로 구분된 목록을 포함합니다. 이 키들을 재정렬하면 항목들도 재정렬됩니다. 리스트 키는 "동일한" 항목들을 정렬하는 경우 여러 리스트에 사용할 수 있습니다. HTML은 같을 필요는 없고, 정렬되는 단어만 같으면 됩니다. 예를 들어, D&D의 "기술" 목록은 완전히 다른 HTML로 시트의 여러 곳에 나타날 수 있지만 모두 같은 리스트 키를 사용할 수 있습니다. 아래 예시 코드를 사용하여 나의 리스트 키를 생성합니다.
"skills-list":"곡예,비밀공작,손재주,생존"
체코어로 이 리스트를 재정렬하려면, 리스트 키-값은 다음과 같을 것입니다:
"skills-list":"곡예,손재주,비밀공작,생존"
예시:
<div data-i18n-list="skills-list"> // 목록 컨테이너에 라벨을 지정하고 정렬에 사용할 키를 가리킵니다. <div> // 주의: 아이템들은 서브 컨테이너에 있습니다. 이 컬럼들은 재정렬 이후에도 유지됩니다. <div data-i18n-list-item="acrobatics"> // 목록 아이템에 라벨을 지정합니다. 이 블록들이 재정렬될 것입니다. <span data-i18n="acrobatics-u">연기기</span> <input type="text" name="attr_npc_acrobatics" placeholder="0"> </div> <div data-i18n-list-item="arcana"> <span data-i18n="arcana-u">비밀학</span> <input type="text" name="attr_npc_arcana" placeholder="0"> </div> </div> <div> <div data-i18n-list-item="sleight-of-hand"> <span data-i18n="sleight-of-hand-u">손재주</span> <input type="text" name="attr_npc_sleight_of_hand" placeholder="0"> </div> <div data-i18n-list-item="survival"> <span data-i18n="survival-u">생존</span> <input type="text" name="attr_npc_survival" placeholder="0"> </div> </div> </div>
같은 예제 뿐만 아니라, 열을 따라 내려가는 대신에, 우리는 열을 따라 가로로 이동하게 할 것입니다:
<div data-i18n-list="skills-list"> <div> <div data-i18n-list-item="acrobatics" data-i18n-list-item-num="1"> <span data-i18n="acrobatics-u">아크로바틱스</span> <input type="text" name="attr_npc_acrobatics" placeholder="0"> </div> <div data-i18n-list-item="sleight-of-hand" data-i18n-list-item-num="3"> <span data-i18n="sleight-of-hand-u">손놀림</span> <input type="text" name="attr_npc_sleight_of_hand" placeholder="0"> </div> </div> <div> <div data-i18n-list-item="arcana" data-i18n-list-item-num="2"> <span data-i18n="arcana-u">아르카나</span> <input type="text" name="attr_npc_arcana" placeholder="0"> </div> <div data-i18n-list-item="survival" data-i18n-list-item-num="4"> <span data-i18n="survival-u">생존</span> <input type="text" name="attr_npc_survival" placeholder="0"> </div> </div> </div>
2단계, 번역 파일 생성
위의 지침을 따라 시트를 서식 지정한 후에는 번역 파일을 아주 쉽게 생성할 수 있습니다. 에디터에서 시트를 로드한 후게임()으로 이동하여 브라우저의 개발자 도구를 열고 콘솔로 이동합니다. 콘솔의 맨 아래에서 코드를 입력할 수 있는 곳에 "i18nOutput"라고 입력하세요. (입력을 시작하면 자동 완성될 것입니다) 엔터를 눌러 이 객체를 검색하면 해당 요소/플레이스홀더 내의 텍스트와 함께 사용한 모든 키를 포함하는 JSON 문자열이 출력됩니다. 그런 다음 이 텍스트를 원하는 JSON 형식으로 복사한 다음 게임 설정 사용자 정의 시트 영역의 "번역" 탭에 붙여넣으면 됩니다.
번역.json 파일을 수동으로 생성하려면 다음 형식을 사용할 수 있습니다.
{ "key": "문자열", "key-2": "다른 문자열." }
서식 지정된 시트와 사용자 정의 시트에 대한 번역 JSON을 가지고 있다면, 모든 번역이 정확하게 수행되었다면 이전과 똑같이 보일 것입니다.
[번역 키]와 같은 빨간색 텍스트가 보이면 이는 시스템에 사용하도록 지시한 키이지만 번역 JSON에 입력하지 않은 키입니다. JSON을 사용하면 시스템에서 생성된 것들을 볼 수 없습니다.
작동하는 번역 파일을 가지고 있다면, 나머지 시트 코드와 함께 "translation.json"으로 캐릭터 시트 폴더의 루트에 업로드할 수 있습니다. 이 파일은 자동으로 시스템에서 인식되어 Crowdin에 업로드되고 번역될 수 있습니다.
번역 변경하기
생성된 번역을 변경하고 싶다면, translation.json 파일을 편집할 수 있으며, 변경 사항은 번역이 업데이트될 때 다음에 언어 파일에 전파됩니다. 그러나 값이 아직 번역되지 않았더라도 특정 변경 사항은 번역 값을 덮어쓰지 않을 수도 있습니다. 즉, 때로는 translation.json의 변경 사항이 시트에 나타나지 않을 수도 있습니다.
업데이트를 트리거하지 않는 변경 사항은 공백이나 특수 문자만 다른 경우, 문자를 제거하거나 변경하지 않고 문자를 추가하지 않는 경우입니다.
변경 사항을 Roll20에 제출하기
참고
- ACSI - 자동화된 캐릭터 시트 국제화. 언어 태그를 삽입하고 생성하는 동안 시간을 절약할 수 있는 Linux 도구입니다.