106 lines
20 KiB
Python
106 lines
20 KiB
Python
# 사이트 런타임 문구 카탈로그 원본 (v1.3.16) — 이 파일을 고치고 실행하면 locales/site/ko.json, en.json 이 다시 만들어진다.
|
||||
|
|
# 형식: (id, 그룹, 한국어 원문, 영어) — {이름} 은 자리 표시(번역문에도 그대로 둔다)
|
|||
|
|
import json, collections
|
|||
|
|
M = [
|
|||
|
|
# 공통
|
|||
|
|
('common.all','common','전체','All'), ('common.list','common','목록','List'), ('common.delete','common','삭제','Delete'), ('common.confirm','common','확인','OK'),
|
|||
|
|
('common.loading','common','불러오는 중…','Loading…'), ('common.sending','common','보내는 중…','Sending…'), ('common.send','common','보내기','Send'), ('common.submit','common','제출','Submit'),
|
|||
|
|
('common.register','common','등록','Post'), ('common.cancel','common','취소','Cancel'), ('common.name','form','이름','Name'), ('common.nameOptional','form','이름(선택)','Name (optional)'),
|
|||
|
|
('common.email','form','이메일','Email'), ('common.password','form','비밀번호','Password'), ('common.phone','form','연락처','Phone'), ('common.subject','form','제목','Subject'),
|
|||
|
|
('common.content','form','내용','Message'), ('common.date','form','날짜','Date'), ('common.category','form','분류','Category'), ('common.other','common','기타','Other'), ('common.search','nav','검색','Search'),
|
|||
|
|
('common.requiredCheck','error','필수 항목을 확인해 주세요.','Please check the required fields.'), ('common.received','notice','접수되었습니다.','Received.'),
|
|||
|
|
('common.receivedContact','notice','접수되었습니다. 곧 연락드리겠습니다.','Thank you. We will get back to you soon.'), ('common.tooMany','error','요청이 너무 많습니다. 잠시 후 다시 시도해 주세요.','Too many requests. Please try again later.'),
|
|||
|
|
('common.sendFailed','error','전송에 실패했습니다. 잠시 후 다시 시도해 주세요.','Sending failed. Please try again later.'), ('common.networkFailed','error','전송에 실패했습니다. 네트워크를 확인해 주세요.','Sending failed. Please check your network.'),
|
|||
|
|
('common.siteNotFound','error','사이트를 찾을 수 없습니다','Site not found'), ('common.originDenied','error','허용되지 않은 출처입니다','This origin is not allowed'),
|
|||
|
|
# 회원
|
|||
|
|
('members.welcome','members','{name}님 환영합니다.','Welcome, {name}.'), ('members.logout','members','로그아웃','Log out'), ('members.login','members','로그인','Log in'), ('members.signup','members','회원가입','Sign up'),
|
|||
|
|
('members.join','members','가입','Join'), ('members.toLogin','members','로그인으로','Back to log in'), ('members.passwordMin6','members','비밀번호 (6자 이상)','Password (6+ characters)'),
|
|||
|
|
('members.pending','members','가입 신청이 접수되었습니다. 관리자 승인 후 로그인할 수 있습니다.','Your sign-up request was received. You can log in after an administrator approves it.'),
|
|||
|
|
('members.loginRequired','members','회원 로그인 후 볼 수 있습니다.','Please log in to view this.'),
|
|||
|
|
# 게시판
|
|||
|
|
('board.title','board','게시판','Board'), ('board.write','board','글쓰기','Write'), ('board.author','board','글쓴이','Author'), ('board.views','board','조회','Views'),
|
|||
|
|
('board.metaViews','board','· 조회 {n}','· {n} views'), ('board.metaComments','board','· 댓글 {n}','· {n} comments'), ('board.empty','board','아직 글이 없습니다.','No posts yet.'),
|
|||
|
|
('board.secret','board','비밀글','Private post'), ('board.secretAskPw','board','비밀글입니다. 작성 시 입력한 비밀번호를 입력하세요.','This is a private post. Enter the password used when it was written.'),
|
|||
|
|
('board.secretOnlyOwner','board','비밀글입니다. 작성자 또는 관리자만 볼 수 있습니다.','This is a private post. Only the author or an administrator can view it.'),
|
|||
|
|
('board.reply','board','답글','Reply'), ('board.replyPlaceholder','board','답글을 입력하세요','Write a reply'), ('board.commentPlaceholder','board','댓글을 입력하세요','Write a comment'),
|
|||
|
|
('board.commentPw','board','댓글 비밀번호','Comment password'), ('board.comments','board','댓글 {n}','Comments {n}'), ('board.commentSecret','board','비밀 댓글','Private comment'), ('board.commentSubmit','board','댓글 등록','Post comment'),
|
|||
|
|
('board.guestPw','board','비밀번호(수정·삭제용, 4자 이상)','Password (for edit/delete, 4+ characters)'), ('board.guestPwDelete','board','비밀번호(삭제용)','Password (for delete)'),
|
|||
|
|
('board.deleteWithPw','board','삭제(비밀번호)','Delete (password)'), ('board.deleteAskPw','board','삭제하려면 글 비밀번호를 입력하세요','Enter the post password to delete it'), ('board.deleteConfirm','board','이 글을 삭제할까요?','Delete this post?'),
|
|||
|
|
# 문의
|
|||
|
|
('inquiry.title','inquiry','문의하기','Contact us'), ('inquiry.button','inquiry','문의 보내기','Send inquiry'), ('inquiry.type','inquiry','문의 유형','Inquiry type'), ('inquiry.files','inquiry','첨부파일','Attachments'),
|
|||
|
|
('inquiry.fileTooBig','error','첨부파일이 너무 큽니다 (최대 {mb}MB)','Attachment is too large (max {mb} MB)'),
|
|||
|
|
('consent.privacy','consent','문의 처리를 위한 개인정보 수집·이용에 동의합니다.','I agree to the collection and use of my personal information to handle this inquiry.'),
|
|||
|
|
# 예약
|
|||
|
|
('booking.title','booking','예약하기','Book now'), ('booking.note','booking','요청 사항','Requests'), ('booking.contactPh','booking','전화 또는 이메일','Phone or email'), ('booking.submit','booking','예약 신청','Request booking'),
|
|||
|
|
('booking.closedDate','booking','예약할 수 없는 날짜입니다.','Bookings are not available on this date.'), ('booking.noSlots','booking','이 날은 예약 시간대가 없습니다.','There are no time slots on this day.'),
|
|||
|
|
('booking.seatsLeft','booking','({n}자리)','({n} left)'), ('booking.confirmed','booking','예약이 확정되었습니다.','Your booking is confirmed.'), ('booking.received','booking','예약이 접수되었습니다. 확인 후 연락드리겠습니다.','Your booking request was received. We will contact you after confirming it.'),
|
|||
|
|
# 갤러리·지도·후기·FAQ·설문
|
|||
|
|
('gallery.title','gallery','갤러리','Gallery'), ('gallery.empty','gallery','등록된 이미지가 없습니다.','No images yet.'),
|
|||
|
|
('map.notFound','map','주소를 찾지 못했습니다: {address}','Address not found: {address}'), ('map.loadFailed','map','지도를 불러오지 못했습니다.','Could not load the map.'), ('map.noAddress','map','주소가 설정되지 않았습니다.','No address is set.'),
|
|||
|
|
('reviews.title','reviews','고객 후기','Reviews'), ('reviews.write','reviews','후기 남기기','Write a review'), ('reviews.placeholder','reviews','후기를 남겨 주세요','Share your experience'), ('reviews.empty','reviews','아직 후기가 없습니다.','No reviews yet.'),
|
|||
|
|
('reviews.low','reviews','★3 이하','★3 or less'), ('reviews.pending','reviews','후기가 접수되었습니다. 확인 후 게시됩니다.','Thank you. Your review will be published after review.'), ('reviews.posted','reviews','후기가 등록되었습니다.','Your review has been posted.'),
|
|||
|
|
('faq.title','faq','자주 묻는 질문','Frequently asked questions'), ('faq.empty','faq','등록된 질문이 없습니다.','No questions yet.'), ('survey.none','survey','진행 중인 설문이 없습니다','There is no active survey'),
|
|||
|
|
# 모듈·폼 API 오류
|
|||
|
|
('err.unknownModule','error','알 수 없는 모듈','Unknown module'), ('err.noAccount','error','계정이 없습니다','Account not found'), ('err.signupClosed','error','회원가입을 받지 않습니다','Sign-up is closed'),
|
|||
|
|
('err.emailFormat','error','이메일 형식을 확인하세요','Please check the email format'), ('err.nameRequired','error','이름을 입력하세요','Please enter your name'), ('err.passwordMin6','error','비밀번호는 6자 이상','Password must be at least 6 characters'),
|
|||
|
|
('err.emailTaken','error','이미 가입된 이메일입니다','This email is already registered'), ('err.loginFailed','error','이메일 또는 비밀번호가 맞지 않습니다','Incorrect email or password'), ('err.approvalPending','error','관리자 승인 대기 중인 계정입니다','This account is waiting for administrator approval'),
|
|||
|
|
('err.siteAdminInput','error','아이디와 6자 이상 비밀번호를 입력하세요','Enter an ID and a password of 6+ characters'), ('err.idTaken','error','이미 있는 아이디입니다','This ID already exists'),
|
|||
|
|
('err.noBoard','error','게시판이 없습니다','Board not found'), ('err.membersOnly','error','회원만 볼 수 있는 게시판입니다','This board is for members only'), ('err.noPost','error','글이 없습니다','Post not found'),
|
|||
|
|
('err.titleBody','error','제목과 내용을 입력하세요','Please enter a title and content'), ('err.guestPwPost','error','비회원은 수정·삭제용 비밀번호(4자 이상)를 입력하세요','Guests must enter a password (4+ characters) for edit/delete'),
|
|||
|
|
('err.noEditPerm','error','수정 권한이 없습니다','You do not have permission to edit'), ('err.noDeletePerm','error','삭제 권한이 없습니다','You do not have permission to delete'), ('err.commentRequired','error','댓글 내용을 입력하세요','Please enter a comment'),
|
|||
|
|
('err.guestPwComment','error','비회원은 삭제용 비밀번호(4자 이상)를 입력하세요','Guests must enter a password (4+ characters) for delete'), ('err.noComment','error','댓글이 없습니다','Comment not found'),
|
|||
|
|
('err.noSurvey','error','설문이 없습니다','Survey not found'), ('err.surveyClosed','error','진행 중인 설문이 아닙니다','This survey is not active'), ('err.alreadyAnswered','error','이미 응답하셨습니다','You have already responded'),
|
|||
|
|
('err.noBooking','error','예약 기능이 없습니다','Booking is not available'), ('err.dateFormat','error','날짜 형식 오류','Invalid date format'), ('err.bookingClosedDate','error','예약할 수 없는 날짜입니다','Bookings are not available on this date'),
|
|||
|
|
('err.slotRequired','error','시간대를 선택하세요','Please choose a time slot'), ('err.slotFull','error','마감된 시간대입니다','This time slot is full'), ('err.nameContact','error','이름과 연락처를 입력하세요','Please enter your name and contact'),
|
|||
|
|
('err.noReviews','error','후기 기능이 없습니다','Reviews are not available'), ('err.reviewRequired','error','후기 내용을 입력하세요','Please enter your review'), ('err.noFaq','error','FAQ 가 없습니다','FAQ not found'), ('err.noGallery','error','갤러리가 없습니다','Gallery not found'),
|
|||
|
|
('err.unknownItem','error','알 수 없는 항목','Unknown item'), ('err.cannotAddHere','error','이 항목은 여기서 추가할 수 없습니다','This item cannot be added here'), ('err.requiredFields','error','필수 항목을 입력하세요','Please fill in the required fields'), ('err.noItem','error','항목이 없습니다','Item not found'),
|
|||
|
|
('err.formName','error','이름을 입력해 주세요.','Please enter your name.'), ('err.formEmail','error','이메일 주소를 확인해 주세요.','Please check your email address.'), ('err.formMessage','error','문의 내용을 입력해 주세요.','Please enter your message.'),
|
|||
|
|
# 사이트 소유자에게 가는 알림 메일
|
|||
|
|
('mail.kindContact','mail','문의','inquiry'), ('mail.kindBooking','mail','예약 문의','booking inquiry'),
|
|||
|
|
('mail.contactSubject','mail','[{site}] {kind}{subject} — {name}','[{site}] New {kind}{subject} — {name}'), ('mail.contactIntro','mail','{site} 웹사이트로 접수된 {kind}입니다.','A new {kind} was received through the {site} website.'),
|
|||
|
|
('mail.fieldKind','mail','종류','Type'), ('mail.fieldReceivedAt','mail','접수 시각','Received at'), ('mail.fieldPage','mail','접수 페이지','Page'), ('mail.content','mail','[내용]','[Message]'),
|
|||
|
|
('mail.replyHint','mail','이 메일에 답장하면 문의자({email})에게 전달됩니다.','Reply to this email to answer the sender ({email}).'),
|
|||
|
|
('mail.surveySubject','mail','[{site}] 설문 응답: {survey} — {who}','[{site}] Survey response: {survey} — {who}'), ('mail.surveyIntro','mail','{site} 사이트의 설문 "{survey}" 에 새 응답이 접수되었습니다.','A new response was submitted to the survey "{survey}" on {site}.'),
|
|||
|
|
('mail.adminPage','mail','관리자 페이지: {url}','Admin page: {url}'),
|
|||
|
|
('mail.bookingSubject','mail','[{site}] 예약 {state}: {date} {time} — {name}','[{site}] Booking {state}: {date} {time} — {name}'), ('mail.bookingConfirmed','mail','확정','confirmed'), ('mail.bookingRequested','mail','신청','requested'),
|
|||
|
|
('mail.bookingIntro','mail','{site} 사이트에 예약이 접수되었습니다.','A booking was received on {site}.'), ('mail.fieldRequest','mail','요청','Request'), ('mail.fieldStatus','mail','상태','Status'),
|
|||
|
|
('mail.statusAuto','mail','자동 확정','Confirmed automatically'), ('mail.statusManual','mail','관리자 확인 필요','Needs administrator confirmation'),
|
|||
|
|
('mail.reviewSubject','mail','[{site}] 새 후기 {stars} — {name}','[{site}] New review {stars} — {name}'), ('mail.reviewHint','mail','관리자 페이지에서 공개 여부를 정하세요: {url}','Decide whether to publish it on the admin page: {url}'),
|
|||
|
|
('mail.inquirySubject','mail','[{site}] {category} 문의 — {name}','[{site}] {category} inquiry — {name}'),
|
|||
|
|
# v1.4.18 일정관리 캘린더
|
|||
|
|
('calendar.title','calendar','일정','Schedule'), ('calendar.today','calendar','오늘','Today'), ('calendar.prev','calendar','이전','Previous'), ('calendar.next','calendar','다음','Next'),
|
|||
|
|
('calendar.month','calendar','월간','Month'), ('calendar.week','calendar','주간','Week'), ('calendar.day','calendar','일간','Day'), ('calendar.allDay','calendar','종일','All day'),
|
|||
|
|
('calendar.empty','calendar','이 기간에는 일정이 없습니다.','There are no events in this period.'), ('calendar.more','calendar','+{n}개 더','+{n} more'),
|
|||
|
|
('calendar.lunarPrefix','calendar','음','Lunar'), ('calendar.leap','calendar','윤','Leap'), ('calendar.lunarBased','calendar','음력 기준 일정','Lunar calendar event'),
|
|||
|
|
('calendar.ganjiLabel','calendar','간지','Sexagenary'), ('calendar.termLabel','calendar','절기','Solar term'), ('calendar.location','calendar','장소','Location'),
|
|||
|
|
('calendar.unitTime','calendar','시간 단위','Timed'), ('calendar.unitDay','calendar','일 단위 ({n}일)','Daily ({n} days)'), ('calendar.unitWeek','calendar','주 단위 ({n}주)','Weekly ({n} weeks)'),
|
|||
|
|
('calendar.close','calendar','닫기','Close'), ('calendar.loadFailed','calendar','일정을 불러오지 못했습니다.','Could not load the schedule.'),
|
|||
|
|
('err.noCalendar','error','일정 기능이 없습니다','Calendar is not available'), ('err.eventDate','error','일정 날짜를 확인하세요 (양력 YYYY-MM-DD 또는 음력 연·월·일 1~30)','Please check the event date (solar YYYY-MM-DD or lunar year/month/day 1–30)'),
|
|||
|
|
('err.eventTime','error','시작 시각은 HH:MM 형식으로 입력하세요','Enter the start time as HH:MM'), ('err.rangeTooLong','error','조회 기간은 최대 {n}일입니다','The range may be at most {n} days'),
|
|||
|
|
# 법적 고지·쿠키·동의 (data-wm-legal 자리에 언어별로 채움)
|
|||
|
|
('legal.copyright','legal','© {year} {name}. 모든 권리 보유.','© {year} {name}. All rights reserved.'), ('legal.privacy','legal','개인정보처리방침','Privacy Policy'), ('legal.terms','legal','이용약관','Terms of Use'),
|
|||
|
|
('legal.cookieNotice','legal','이 사이트는 서비스 제공과 이용 통계를 위해 쿠키를 사용합니다.','This site uses cookies to provide its services and measure usage.'), ('legal.cookieAccept','legal','동의','Accept'), ('legal.cookieDecline','legal','거부','Decline'),
|
|||
|
|
('legal.businessInfo','legal','상호 {name} · 대표 {owner} · 사업자등록번호 {bizNo}','{name} · Representative {owner} · Business registration no. {bizNo}'),
|
|||
|
|
('lang.label','nav','언어','Language'),
|
|||
|
|
('err.loginRequired','error','로그인이 필요합니다','Please log in'), ('err.inquiryOff','error','문의 기능이 꺼져 있습니다','Inquiries are turned off'), ('err.surveyOff','error','설문 기능이 꺼져 있습니다','Surveys are turned off'),
|
|||
|
|
('err.bookingOff','error','예약 기능이 꺼져 있습니다','Booking is turned off'), ('err.tryLater','error','잠시 후 다시 시도하세요','Please try again later'), ('err.addressNotFound','error','주소를 찾지 못했습니다','Address not found'),
|
|||
|
|
('mail.attachments','mail','[첨부] {files}','[Attachments] {files}'),
|
|||
|
|
# v1.4.0 블로그·자료실
|
|||
|
|
('blog.title','blog','블로그','Blog'), ('blog.searchPh','blog','블로그 글 검색','Search posts'), ('blog.empty','blog','아직 글이 없습니다.','No posts yet.'), ('blog.noResults','blog','검색 결과가 없습니다.','No results found.'),
|
|||
|
|
('blog.readMore','blog','더 보기','Read more'), ('blog.back','blog','목록으로','Back to list'), ('blog.views','blog','조회 {n}','{n} views'), ('blog.comments','blog','댓글 {n}','Comments ({n})'),
|
|||
|
|
('blog.commentPh','blog','댓글을 남겨 주세요','Leave a comment'), ('blog.commentSubmit','blog','댓글 남기기','Post comment'), ('blog.commentPending','blog','댓글이 접수되었습니다. 관리자 확인 후 보입니다.','Thanks! Your comment will appear after review.'),
|
|||
|
|
('blog.commentPosted','blog','댓글이 등록되었습니다.','Your comment has been posted.'), ('blog.commentsClosed','blog','댓글을 받지 않는 글입니다.','Comments are closed.'), ('blog.tagAll','blog','모든 태그','All tags'),
|
|||
|
|
('library.title','library','자료실','Downloads'), ('library.searchPh','library','자료 검색','Search files'), ('library.empty','library','등록된 자료가 없습니다.','No files yet.'), ('library.download','library','내려받기','Download'),
|
|||
|
|
('library.downloads','library','내려받음 {n}','{n} downloads'), ('library.memberOnly','library','회원만 내려받을 수 있습니다. 로그인해 주세요.','Please log in to download.'),
|
|||
|
|
('err.noBlog','error','블로그가 없습니다','Blog not found'), ('err.noLibrary','error','자료실이 없습니다','Downloads not found'), ('err.fileMissing','error','파일을 찾을 수 없습니다','File not found'), ('err.commentsClosed','error','댓글을 받지 않습니다','Comments are closed'),
|
|||
|
|
('contact.messageLabel','inquiry','문의 내용','Message'), ('contact.bookingMessageLabel','booking','예약 희망 일시와 요청 사항','Preferred date/time and requests'), ('contact.bookingButton','booking','예약 문의 보내기','Send booking request'),
|
|||
|
|
]
|
|||
|
|
ids = [m[0] for m in M]; assert len(ids) == len(set(ids)), [i for i in ids if ids.count(i) > 1]
|
|||
|
|
GROUP = {'common':'공통','form':'폼 입력','nav':'내비게이션','error':'오류 메시지','notice':'안내','members':'회원','board':'게시판','inquiry':'문의','consent':'동의문','booking':'예약','gallery':'갤러리','map':'지도','reviews':'후기','faq':'FAQ','survey':'설문','blog':'블로그','library':'자료실','calendar':'일정관리','mail':'메일 알림','legal':'법적 고지·쿠키'}
|
|||
|
|
ko = collections.OrderedDict(); en = collections.OrderedDict()
|
|||
|
|
for i, g, k, e in M: ko[i] = {'text': k, 'group': GROUP[g]}; en[i] = e
|
|||
|
|
head = {'about': '생성 사이트의 시스템 문구(모듈 위젯·폼·오류·동의문·예약·문의·메일 알림·법적 고지) 원본. 코드에는 id 만 쓰고 글자는 이 파일에서 가져온다(lib/sitemsg.js). 번역은 locales/site/<언어>.json(id → 번역문) 과 data/site-i18n/_runtime/<언어>.json(AI 번역 캐시)에 둔다. {이름} 자리 표시는 번역문에도 그대로 둔다.', 'formatVersion': 1}
|
|||
|
|
json.dump({**head, 'count': len(ko), 'messages': ko}, open('locales/site/ko.json', 'w'), ensure_ascii=False, indent=1)
|
|||
|
|
json.dump({'lang': 'en', 'formatVersion': 1, 'messages': en}, open('locales/site/en.json', 'w'), ensure_ascii=False, indent=1)
|
|||
|
|
print(len(ko), 'messages')
|