본문 바로가기
javascript

대규모 프런트 엔드 코드베이스에서 모든 i18n 키를 다시 쓰는 중

by it-square 2022. 1. 19.
반응형

저와 제 팀은 흥미로운 도전을 받았습니다. 우리는 모든 i18n 변환에 대한 진실 출처를 하드 코딩된 JSON 파일에서 인기 있는 제3자 국제화 서비스인 구에서 가져온 자동 생성 JSON 파일로 변경하는 과정에 있었다.

도전은 다음과 같습니다. 또한 이번 기회에 코드베이스의 번역 키를 보다 깨끗하고 쉽게 추론할 수 있도록 완전히 다시 작성하기로 결정했습니다.

이 업무는 상당한 팀워크가 필요했고, 제 동료 개발자들 중 몇 명은 이 업무의 다른 면을 맡았습니다. 이 기사에서는 주로 이 작업에 대한 제 작업과 그 작업에 투입된 몇 가지 영리한 자동화에 대해 말씀드리겠습니다.

하지만 먼저 내 손에 떨어지기 전에 무슨 일이 있었는지부터 살펴보죠 저희 팀의 개발자 중 두 명은 500개 미만의 기존 번역 키를 통해 구문 분석 및 생각을 하는 일을 했습니다. 새 변환의 네임스페이스는 사용된 페이지, 페이지의 섹션 등에 따라 추가 중첩이 필요한 경우 지정되었습니다. 즉, 많은 변환이 이 새 스키마에 맞게 복제, 제거 또는 이동되어야 합니다.
일일이 번역을 하다 보니 개념화, 검증이 많이 필요하고 진행이 느려서 더 어려운 과제를 안게 된 것 같다.
원본 변환 파일은 다음과 같을 수 있습니다.

이 작은 조각에서도 알 수 있듯이, 수십 명의 개발자들이 수 년 동안 점진적으로 수정한 후 많은 표준화가 사라졌습니다. 때로는 완전히 분리된 프런트엔드 팀에서도 마찬가지입니다.

 

따라서, 결국 두 개발자는 코드베이스 업데이트와 구문을 수입하기 위한 출발 기반으로 사용할 수 있는 깨끗하고 이해하기 쉬운 새로운 JSON을 제작했습니다.

이제 저와 저와 함께 작업하던 개발자는 새로운 번역 JSON을 가져와서 모든 원래 번역 키 문자열을 새로운 대체 문자열로 교체하기 시작했습니다.
매우 단순하고 거의 동일한 대체품은 다음과 같습니다.

useTranslation() hook에서 t() 메서드가 떨어져 나오는 것에 대해 궁금하다면 다음 i18n 설명서를 확인하십시오! 간단히 말해, 현재 언어 및 국가 로케일의 범위 내에서 번역 텍스트를 참조하고 액세스하는 방법입니다.

이 작업은 자동화가 무르익었습니다! 진지한 작업을 하기 전에 저와 공동 개발자는 코드베이스를 조사하여 작업의 범위와 마주칠 수 있는 "이상한 일"을 파악했습니다. 몇 가지 고전적인 RegExing을 사용하여 두 저장소 사이에 약 18,000개의 관련 파일과 750개 미만의 번역 사용이 분산되어 있다는 것을 발견했습니다.
우리는 또한 약간의 문제를 발견했는데, JSON의 모든 원본 번역 파일을 합친 결과 이전 개발자들이 작업했던 초기 500개가 아닌 700개 이상의 다른 번역이 생성되었습니다. 아차! 그래도 괜찮아요. 이전 개발자들이 만든 표준 때문에 누락된 번역에 대한 새로운 네임스페이스를 만드는 데 오래 걸리지 않았어요.

처음에 스카우트 작업을 자동화하기 위해 생각해낸 해결책은 모든 번역에 대한 문자열 경로를 만들고 렌더링된 영어 텍스트에 묶는 JSON 트리 워킹 스크립트를 작성하는 것이었습니다. 두 변환 파일 모두에 대해 이 작업을 수행합니다(하나는 결합된 원래 변환 JSON 파일이고 두 번째는 새로 생성된 구문 변환 JSON 파일). 그런 다음 렌더링된 텍스트를 원래 키와 교체 키 사이의 결합처럼 사용합니다.
예를 들어, 각 참조는 다음과 같습니다.

 

이렇게 일치하는 상대들의 방대한 컬렉션을 가지고 나면, 우리는 모든 원본 변환을 수행할 다른 스크립트를 만들 수 있고, 코드베이스 디렉터리를 하나씩 재귀적으로 반복하여 관련 파일 형식을 발견하면, i18n t() 메소드를 사용하는 모든 곳을 찾기 위해 find-regex를 실행할 수 있다. t()에서 원래 변환 키가 발견되면 대체 키로 교환됩니다!

요약하자면, 계획은 다음과 같습니다.
1: JSON 파일에 대한 스크립트를 작성합니다.
2: 이 스크립트를 사용하여 각 변환 파일에 대한 전체 키 참조를 생성하고 렌더링된 텍스트를 기반으로 원본 및 대체 파일로 연결합니다.
3: 원본 키와 교체 키 모음을 사용하여 코드베이스 파일을 전체적으로 살펴보고 원본 키의 각 인스턴스를 해당 대체 키로 바꿉니다.

1: JSON 트리 워킹 스크립트

이 부분에 대해서는 이 작업만이 아니라 어디에서나 사용할 수 있는 작은 도구를 만드는 데 시간을 할애했습니다. 저는 과거에 JSON 트리 워킹 스크립트를 많이 작성해야 했기 때문에 지금이야말로 재사용할 수 있는 도구로 만들 수 있다고 생각했습니다. NPM에서 실제로 사용할 수 있지만 간단히 말해, 이 도구는 사용자가 처리하고자 하는 모든 종류의 자바스크립트 원초적인 것에 대한 콜백 메소드를 제공할 수 있는 사용하기 쉬운 API를 제공합니다. 네이티브 Array.protype.reduce() 메서드와 매우 유사하지만 개체의 모든 중첩 속성에 대해 재귀적으로 작동합니다!

2: 조인된 키 참조 생성

 

이 단계에서는 json-tree-walker 툴을 사용하여 기존 변환 JSON 파일과 교체 JSON 파일을 모두 트래버스했습니다. 각 단계에서 JSON을 통해 현재 지점에 도달할 수 있는 경로인 문자열에 대한 키가 결합됩니다. 문자열을 누른 후 경로 문자열에 키를 추가한 다음 해당 번역의 렌더링된 텍스트를 기반으로 조인된 번역 모음에 키를 추가합니다. 각 항목에 대한 객체의 모양에 대한 참조는 이전 코드 예제를 참조하십시오.

하지만, 저는 어려운 문제에 부딪혔습니다. 우리가 렌더링한 많은 번역 텍스트들이 원본과 교체된 JSON 파일 모두에서 많은 장소에서 재사용되고 있는 것으로 밝혀졌습니다. 이것은 분명히 의도적인 것이므로, 저는 이 사건을 처리하기 위해 이 대본에 추가 부분을 작성해야 했습니다. 예를 들어, "cancel"이라는 단어는 웹사이트의 많은 다른 장소에서 사용될 수 있으므로, "cancel"을 렌더링된 텍스트로 사용하는 다양한 번역이 있을 것이다. 이로 인해 렌더링된 텍스트를 원래/바꾸기 변환 키 사이의 조인어로 사용할 때 문제가 발생했습니다. 나는 우리의 과정에 한 단계를 더 추가해야 했어요.

2.5: 수동 개입을 위한 중복 문자열 수집

이를 위해 JSON을 실행하는 동안 발견된 모든 키를 원래 키와 교체 키 모두를 위한 임시 배열에 저장하였다. 이 시점에서 스크립트가 어느 것과 어떤 링크를 연결할지 결정할 만큼 똑똑하지 않았기 때문에 수동 개입 시스템을 구현하기로 결정했습니다. 저는 Inquirer 도구를 사용하여 깨끗하고 쉬운 CLI 옵션 선택을 제공했습니다. 번역본이 1개 이상이거나 대체 번역본이 1개 이상일 경우, 원문을 반복하여 각각의 원문에 대해 질문을 추가하면 옵션이 모두 대체됩니다.
우리가 원래 가지고 있던 번역은 삭제 계정이라고 합시다.CancelText 및 공통입니다.취소하세요. 대체 옵션은 계정이 있습니다.삭제.취소 및 홈페이지.피드백.취소해 어떤게 좋을지 분석해보셨다면 3가지 다른 시나리오가 있다는걸 아실겁니다 계정 삭제 페이지(쉬운 페이지), 피드백 페이지 및 새 구문 변환에서 제거되는 모든 "공통" 섹션이 있습니다. 결정하기 좀 까다롭죠? 이것은 확실히 알기 위해 조사가 필요한 많은 것 중 하나일 것이다. CLI에서는 accountDelete의 가치를 보여줍니다.CancelText 및 Account 옵션을 선택합니다.삭제.취소 및 홈페이지.피드백.취소. 옵션을 선택한 후에는 공통으로 적용됩니다.취소하다.

스크립트가 모든 자동 일치를 생성한 후(일대일 일치만 있었던 경우), 모든 수동 개입 질문을 생성하고, 개발자가 나머지 모든 일치를 수동으로 선택한 후, 스크립트는 모든 원본 변환 키를 대체 상대방과 매핑한 새로운 JSON 파일을 만듭니다. 이때, 힘든 일은 대부분 끝이 났습니다!

 

이 모든 것이 코드에서 어떻게 보일 수 있는지에 대해, 여기 토막글이 있다:
(참고: 이것은 적은 양의 코드가 아니며 매우 혼잡하므로, 당신이 그것을 이해하고 싶다면 천천히 하세요. 그렇지 않으면 이 비트는 건너뛰셔도 됩니다.)

3: 코드베이스에 따라 모든 원래 키를 교체합니다.

이 단계는 매우 간단하지만 파일 시스템 위에 몇 가지 까다로운 재귀가 수반됩니다. 데이터를 사용하여 변환 키를 즉시 교환하는 대신 이전 단계의 결과를 다른 파일로 저장할 때의 가장 큰 이점은 코드베이스에 사용되었지만 원본 변환 파일(oops!)에는 없는 몇 가지 오류와 몇 가지 누락된 키가 있다는 것입니다. 이 기술을 통해 joined_translations.json 파일을 쉽게 수정할 수 있으며 향후 모든 사례에 대해서도 수정될 수 있습니다!

joined_translations.json 파일에 대한 확신이 생긴 후 새 스크립트로 가져올 수 있으며 이 파일은 우리가 수행하고자 하는 모든 대체물의 새로운 모음으로 사용될 것입니다.
다시 한 번 말씀드리지만, 저희가 가입한 번역 파일은 다음과 같습니다.

새로운 스크립트를 사용하면 원하는 코드베이스의 루트 경로와 상대 컬렉션의 경로를 전달할 수 있습니다. 필요한 정보는 여기까지입니다! 여기서부터 모든 상대 객체를 루프한 다음 코드베이스를 따라 반복적으로 이동할 수 있습니다. 파일을 볼 때마다 파일의 내용을 열고 찾기 바꾸기를 실행한 다음 파일을 새 콘텐츠로 덮어쓰도록 했습니다!

 

이 스크립트는 상당히 빠르게 실행될 수 있습니다. 18,000개의 모든 관련 파일을 실행하는 데 약 180-250초가 소요됩니다. 하지만, 저는 공정 순서를 변경하여 더 빨리 진행할 수 있었습니다. 이 스크립트를 번역할 때마다 코드베이스를 위에서 아래로 돌려야 했던 게 실수였다. 즉, 500개의 번역어가 있다면 전체 코드베이스를 500번 정도 반복해야 한다는 뜻입니다. 아이고! 코드베이스를 한 번 실행하고 파일을 볼 때마다 해당 파일의 모든 변환을 한 번에 찾은 다음 계속 진행하면 됩니다.

이 단계의 코드는 다음과 비슷합니다.

결론

모든 것이 전체적으로 순조롭게 작동했어요! 이 과정이 끝날 무렵, 코드베이스 내에서 약 700개의 번역이 변경되었다. 나머지는 수동으로 수정해야 하는 t() 방법의 특별한 경우 또는 비표준 사용이었다. 이 코드베이스에서 우리는 또한 많은 유닛 테스트를 구현했고, 그 중 많은 유닛 테스트를 새로운 번역 키를 처리하기 위해 업데이트해야 했다.

 

프로세스가 끝날 때쯤에는 이 프로세스를 최대한 자동화함으로써 지루한 육체 노동을 며칠 동안 줄일 수 있었습니다. 그건 제가 자랑스러운 일이에요!

댓글