Files
discourse-korean-localization/scripts/verify_runtime.rb
T
syskiller 5bad207526 포럼 한국어 번역 플러그인을 복구하고 배포 검사를 보강
비어 있던 운영 플러그인 경로를 전용 서비스 원본으로 복구했다.
음성 입장 안내와 주변 메뉴 및 관리자 번역을 실제 화면에서 확인했다.
관리자 주소용 내부 이름을 보존하고 보드 메뉴 두 곳의 제목을 복구했다.

검사: Ruby 문법과 YAML 11개 통과. 활성 번역 6004개와 음성 번역 561개 누락 0개.
일반 화면과 관리자 번역 및 보드 자산의 제공 해시를 확인했다.
PC와 390픽셀 모바일 안내창 및 관리자 메뉴 주소를 확인했다.
운영: app 컨테이너만 갱신. DB 구조 변경과 데이터 이전 없음.
백업: /var/discourse/shared/standalone/backups/forum-korean-20261015-1150
설정 백업은 별도 비밀 디렉터리의 권한 600 파일로 보관했다.
제한: DB 복원 시험과 다음 컨테이너 재생성은 이번 검사에 포함하지 않았다.
Trilium: Ubuntu 서버 운영 아래 Discourse 한국어 배포에 기록했다.
2026-10-14 22:44:52 +00:00

65 lines
3.3 KiB
Ruby

# frozen_string_literal: true
require "json"
require "digest"
require "yaml"
abort "한국어 보완 플러그인을 불러오지 못했습니다." unless Discourse.plugins.any? { |plugin| plugin.name == "itosm-korean-localization" }
abort "이전 한국어 플러그인이 중복 설치되어 있습니다." if Discourse.plugins.any? { |plugin| plugin.name == "itosm-admin-korean" }
I18n.with_locale(:ko) do
boards = Discourse.plugins.find { |plugin| plugin.name == "boards" }
if boards
serialized = AdminPluginSerializer.new(boards, root: false).as_json
abort "플러그인 내부 이름이 번역되어 관리자 링크가 손상됩니다." unless serialized[:name] == "boards"
abort "보드 표시 이름 번역 누락" unless serialized[:humanized_name] == "보드"
end
end
expected = {
"title" => "대화방에 참여하기 전에 확인해 주세요.",
"join" => "대화방 참여",
"cancel" => "취소",
"dont_show_again" => "다시 표시하지 않기",
}
expected.each do |key, value|
actual = I18n.t("js.voice.mesh_privacy_warning.#{key}", locale: :ko, fallback: false)
abort "음성 대화방 번역 불일치: #{key}" unless actual == value
end
body = I18n.t("js.voice.mesh_privacy_warning.body", locale: :ko, fallback: false)
abort "음성 대화방 개인정보 안내 번역 누락" unless body.include?("다른 참여자가 내 IP 주소를 확인할 수 있습니다.")
def flatten_translations(hash, prefix = "", result = {})
hash.each do |key, value|
path = prefix.empty? ? key.to_s : "#{prefix}.#{key}"
value.is_a?(Hash) ? flatten_translations(value, path, result) : result[path] = value
end
result
end
korean = flatten_translations(I18n.backend.send(:translations).fetch(:ko))
TranslationOverride.where(locale: "ko").pluck(:translation_key, :value).each { |key, value| korean[key] = value }
active_keys = Discourse.plugins.select(&:enabled?).flat_map do |plugin|
Dir.glob(Rails.root.join("plugins", plugin.directory_name, "config/locales/*.en.yml")).flat_map do |path|
flatten_translations(YAML.safe_load_file(path, aliases: true).fetch("en", {})).keys
end
end.uniq
# 한국어는 단수와 복수에 같은 표현을 사용하므로 other가 있으면 one도 충족합니다.
missing = active_keys.reject do |key|
korean.key?(key) || (key.end_with?(".one") && korean.key?(key.sub(/\.one$/, ".other")))
end
abort "활성 플러그인 한국어 번역 누락 #{missing.size}개: #{missing.first(10).join(', ')}" unless missing.empty?
# 영어 대체 표시를 정상 번역으로 오인하지 않도록 한국어 묶음의 내용 해시를 반환합니다.
bundles = %w[main admin].to_h do |bundle|
content = ExtraLocalesController.bundle_js(bundle, locale: :ko)
[bundle, { url: ExtraLocalesController.url(bundle, locale: :ko), sha256: Digest::SHA256.hexdigest(content) }]
end
if Discourse.plugins.any? { |plugin| plugin.name == "boards" }
filename = Plugin::JsManager.read_manifest("boards").dig("main", "fileName")
board_js = File.read(Rails.root.join("app/assets/generated/boards/js/plugins", filename))
abort "보드 메뉴 제목 컴파일 누락" unless board_js.include?("보드 메뉴") && board_js.include?("열 메뉴")
bundles["boards"] = {url: "/assets/js/plugins/#{filename}", sha256: Digest::SHA256.hexdigest(board_js)}
end
puts JSON.generate(bundles: bundles, active_plugin_keys: active_keys.size, missing: missing.size)