├── .gitignore ├── smiti18n ├── version.lua ├── variants.lua ├── interpolate.lua ├── format.lua ├── plural.lua └── init.lua ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── release.yml │ └── ci.yml ├── .actrc ├── .busted ├── .luacov ├── LICENSE ├── rockspecs ├── smiti18n-0.9.3-1.rockspec ├── smiti18n-0.9.4-1.rockspec └── smiti18n-0.9.5-1.rockspec ├── locales ├── ja-JP.lua ├── ko-KR.lua ├── ca-ES.lua ├── cs-CZ.lua ├── tr-TR.lua ├── de-DE.lua ├── eo-EO.lua ├── ru-RU.lua ├── sk-SK.lua ├── fr-FR.lua ├── sr-SR.lua ├── es-ES.lua ├── no-NB.lua ├── sv-SE.lua ├── da-DK.lua ├── id-ID.lua ├── it-IT.lua ├── nl-NL.lua ├── en-US.lua ├── hr-HR.lua ├── hu-HU.lua ├── en-CA.lua ├── en-NZ.lua ├── en-UK.lua ├── hi-IN.lua ├── pl-PL.lua ├── uk-UA.lua ├── en-AU.lua ├── el-GR.lua ├── fi-FI.lua ├── ar-SA.lua ├── he-IL.lua ├── zh-SG.lua ├── zh-MO.lua ├── ko.lua └── ja.lua ├── spec ├── data │ └── en-UK.lua ├── test_variants.lua ├── test_plural.lua └── test_interpolate.lua └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | artifacts/* 2 | -------------------------------------------------------------------------------- /smiti18n/version.lua: -------------------------------------------------------------------------------- 1 | return '0.9.5' 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: flexiondotorg 2 | -------------------------------------------------------------------------------- /.actrc: -------------------------------------------------------------------------------- 1 | --secret-file=$HOME/.config/act/secrets 2 | --artifact-server-path=./artifacts 3 | --pull=false 4 | -------------------------------------------------------------------------------- /.busted: -------------------------------------------------------------------------------- 1 | return { 2 | default = { 3 | ROOT = {"spec"}, 4 | pattern = "test_.*%.lua$", 5 | coverage = true, 6 | verbose = true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.luacov: -------------------------------------------------------------------------------- 1 | return { 2 | include = { 3 | "smiti18n/.*" 4 | }, 5 | exclude = { 6 | ".luarocks/.*", 7 | "spec/.*", 8 | "spec/data/.*" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | # Check for updates to GitHub Actions every week 7 | interval: "weekly" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License Terms 2 | ================= 3 | 4 | Copyright (c) 2012 Enrique García Cota. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 10 | of the Software, and to permit persons to whom the Software is furnished to do 11 | so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /rockspecs/smiti18n-0.9.3-1.rockspec: -------------------------------------------------------------------------------- 1 | local _version = "0.9.3" 2 | local _revision = "1" 3 | 4 | package = "smiti18n" 5 | version = _version .. "-" .. _revision 6 | source = { 7 | url = ("https://github.com/Oval-Tutu/smiti18n/archive/%s.tar.gz"):format(_version), 8 | dir = ("smiti18n-%s"):format(_version) 9 | } 10 | description = { 11 | summary = "A very complete internationalization library for Lua with LÖVE support", 12 | detailed = [[ 13 | smiti18n is a full-featured i18n library for Lua with LÖVE integration. 14 | It handles hierarchies of tags, accepts entries in several ways (one by one, 15 | in a table or in a file), and implements extensive pluralization rules, 16 | fallbacks, arrays, and multiple locale support. 17 | ]], 18 | homepage = "https://github.com/Oval-Tutu/smiti18n", 19 | license = "MIT" 20 | } 21 | dependencies = { 22 | "lua >= 5.1" 23 | } 24 | build = { 25 | type = "builtin", 26 | modules = { 27 | ["smiti18n.init"] = "smiti18n/init.lua", 28 | ["smiti18n.plural"] = "smiti18n/plural.lua", 29 | ["smiti18n.variants"] = "smiti18n/variants.lua", 30 | ["smiti18n.interpolate"] = "smiti18n/interpolate.lua" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /smiti18n/variants.lua: -------------------------------------------------------------------------------- 1 | local variants = {} 2 | 3 | local function reverse(arr, length) 4 | local result = {} 5 | for i=1, length do result[i] = arr[length-i+1] end 6 | return result, length 7 | end 8 | 9 | function variants.ancestry(locale) 10 | local result, length, accum = {},0,nil 11 | locale:gsub("[^%-]+", function(c) 12 | length = length + 1 13 | accum = accum and (accum .. '-' .. c) or c 14 | result[length] = accum 15 | end) 16 | return reverse(result, length) 17 | end 18 | 19 | function variants.isParent(parent, child) 20 | return not not child:match("^".. parent .. "%-") 21 | end 22 | 23 | function variants.root(locale) 24 | return locale:match("[^%-]+") 25 | end 26 | 27 | function variants.fallbacks(locales) 28 | local in_seen = {} 29 | local out_seen = {} 30 | local ancestry, length = {}, 0 31 | for index, value in ipairs(locales) do 32 | if not in_seen[value] then 33 | in_seen[value] = true 34 | local ancestry1, length1 = variants.ancestry(value) 35 | for i = 1, length1 do 36 | if not out_seen[ancestry1[i]] then 37 | out_seen[ancestry1[i]] = true 38 | ancestry[#ancestry + 1] = ancestry1[i] 39 | end 40 | end 41 | end 42 | end 43 | 44 | return ancestry, length 45 | end 46 | 47 | return variants 48 | -------------------------------------------------------------------------------- /locales/ja-JP.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["ja-JP"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "円", 6 | name = "日本円", 7 | short_name = "円", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%p%q%c", 14 | negative_format = "%p%q%c", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%Y年 %F %d日 %l", 25 | short_date = "%Y.%m.%d", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%Y.%m.%d %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%Y年 %F %d日 %l %g:%i:%s", 30 | }, 31 | short_month_names = { 32 | "1月", 33 | "2月", 34 | "3月", 35 | "4月", 36 | "5月", 37 | "6月", 38 | "7月", 39 | "8月", 40 | "9月", 41 | "10月", 42 | "11月", 43 | "12月", 44 | }, 45 | long_month_names = { 46 | "1月", 47 | "2月", 48 | "3月", 49 | "4月", 50 | "5月", 51 | "6月", 52 | "7月", 53 | "8月", 54 | "9月", 55 | "10月", 56 | "11月", 57 | "12月", 58 | }, 59 | short_day_names = { 60 | "日", 61 | "月", 62 | "火", 63 | "水", 64 | "木", 65 | "金", 66 | "土", 67 | }, 68 | long_day_names = { 69 | "日曜日", 70 | "月曜日", 71 | "火曜日", 72 | "水曜日", 73 | "木曜日", 74 | "金曜日", 75 | "土曜日", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/ko-KR.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["ko-KR"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "KRW", 6 | name = "Korea (South) Won", 7 | short_name = "Won", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%l, 년%Y %F %d요일", 25 | short_date = "년%Y.%m.%d", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%Y.%m.%d %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l, 년%Y %F %d요일 %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "1월", 33 | "2월", 34 | "3월", 35 | "4월", 36 | "5월", 37 | "6월", 38 | "7월", 39 | "8월", 40 | "9월", 41 | "10월", 42 | "11월", 43 | "12월", 44 | }, 45 | long_month_names = { 46 | "1월", 47 | "2월", 48 | "3월", 49 | "4월", 50 | "5월", 51 | "6월", 52 | "7월", 53 | "8월", 54 | "9월", 55 | "10월", 56 | "11월", 57 | "12월", 58 | }, 59 | short_day_names = { 60 | "일요일", 61 | "월요일", 62 | "화요일", 63 | "수요일", 64 | "목요일", 65 | "금요일", 66 | "토요일", 67 | }, 68 | long_day_names = { 69 | "일요일", 70 | "월요일", 71 | "화요일", 72 | "수요일", 73 | "목요일", 74 | "금요일", 75 | "토요일", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/ca-ES.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["ca-ES"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "€", 6 | name = "Euro", 7 | short_name = "EUR", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d/%m/%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%d %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Gen", 33 | "Feb", 34 | "Mar", 35 | "Abr", 36 | "Mai", 37 | "Jun", 38 | "Jul", 39 | "Ago", 40 | "Set", 41 | "Oct", 42 | "Nov", 43 | "Des", 44 | }, 45 | long_month_names = { 46 | "Gener", 47 | "Febrer", 48 | "Març", 49 | "Abril", 50 | "Maig", 51 | "Juny", 52 | "Juliol", 53 | "Agost", 54 | "Setembre", 55 | "Octubre", 56 | "Novembre", 57 | "Desembre", 58 | }, 59 | short_day_names = { 60 | "Dg", 61 | "Dl", 62 | "Dm", 63 | "Dc", 64 | "Dj", 65 | "Dv", 66 | "Ds", 67 | }, 68 | long_day_names = { 69 | "Diumenge", 70 | "Dilluns", 71 | "Dimarts", 72 | "Dimercres", 73 | "Dijous", 74 | "Divendres", 75 | "Dissabte", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/cs-CZ.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["cs-CZ"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "Kč", 6 | name = "Koruna česká", 7 | short_name = "Kč", 8 | decimal_symbol = ",", 9 | thousand_separator = " ", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%p%q %c", 14 | negative_format = "%p%q %c", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = " ", 22 | }, 23 | date_time = { 24 | long_date = "%d. %F %Y", 25 | short_date = "%d.%m.%Y", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d.%m.%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%d. %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Led", 33 | "úno", 34 | "Bře", 35 | "Dub", 36 | "Kvě", 37 | "čvn", 38 | "čec", 39 | "Srp", 40 | "Zář", 41 | "říj", 42 | "Lis", 43 | "Pro", 44 | }, 45 | long_month_names = { 46 | "Leden", 47 | "únor", 48 | "Březen", 49 | "Duben", 50 | "Květen", 51 | "červen", 52 | "červenec", 53 | "Srpen", 54 | "Září", 55 | "říjen", 56 | "Listopad", 57 | "Prosinec", 58 | }, 59 | short_day_names = { 60 | "Ne", 61 | "Po", 62 | "út", 63 | "St", 64 | "čt", 65 | "Pá", 66 | "So", 67 | }, 68 | long_day_names = { 69 | "Neděle", 70 | "Pondělí", 71 | "úterý", 72 | "Středa", 73 | "čtvrtek", 74 | "Pátek", 75 | "Sobota", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/tr-TR.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["tr-TR"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "₺", 6 | name = "Lira", 7 | short_name = "YTL", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%l, %d.%F %Y", 25 | short_date = "%d.%m.%Y", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d.%m.%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%l, %d.%F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Ock", 33 | "şbt", 34 | "Mrt", 35 | "Nsn", 36 | "May", 37 | "Haz", 38 | "Tem", 39 | "Ağu", 40 | "Eyl", 41 | "Ekm", 42 | "Kas", 43 | "Ara", 44 | }, 45 | long_month_names = { 46 | "Ocak", 47 | "şubat", 48 | "Mart", 49 | "Nisan", 50 | "Mayıs", 51 | "Haziran", 52 | "Temmuz", 53 | "Ağustos", 54 | "Eylül", 55 | "Ekim", 56 | "Kasım", 57 | "Aralık", 58 | }, 59 | short_day_names = { 60 | "Paz", 61 | "Pzt", 62 | "Sal", 63 | "çar", 64 | "Per", 65 | "Cum", 66 | "Crt", 67 | }, 68 | long_day_names = { 69 | "Pazar", 70 | "Pazartesi", 71 | "Salı", 72 | "çarşamba", 73 | "Perşembe", 74 | "Cuma", 75 | "Cumartesi", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/de-DE.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["de-DE"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "€", 6 | name = "Euro", 7 | short_name = "EUR", 8 | decimal_symbol = ",", 9 | thousand_separator = " ", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%p%q %c", 14 | negative_format = "%p%q %c", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = " ", 22 | }, 23 | date_time = { 24 | long_date = "%l, %d. %F %Y", 25 | short_date = "%d.%m.%", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d.%m.%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%l, %d. %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mär", 35 | "Apr", 36 | "Mai", 37 | "Jun", 38 | "Jul", 39 | "Aug", 40 | "Sep", 41 | "Okt", 42 | "Nov", 43 | "Dez", 44 | }, 45 | long_month_names = { 46 | "Januar", 47 | "Februar", 48 | "März", 49 | "April", 50 | "Mai", 51 | "Juni", 52 | "Juli", 53 | "August", 54 | "September", 55 | "Oktober", 56 | "November", 57 | "Dezember", 58 | }, 59 | short_day_names = { 60 | "So", 61 | "Mo", 62 | "Di", 63 | "Mi", 64 | "Do", 65 | "Fr", 66 | "Sa", 67 | }, 68 | long_day_names = { 69 | "Sonntag", 70 | "Montag", 71 | "Dienstag", 72 | "Mittwoch", 73 | "Donnerstag", 74 | "Freitag", 75 | "Samstag", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/eo-EO.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["eo-EO"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "€", 6 | name = "Euro", 7 | short_name = "EUR", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c%p%q", 14 | negative_format = "%c%p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%Y-%m-%d", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%Y-%m-%d %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%l %d %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mar", 35 | "Apr", 36 | "Maj", 37 | "Jun", 38 | "Jul", 39 | "Aŭg", 40 | "Sep", 41 | "Okt", 42 | "Nov", 43 | "Déc", 44 | }, 45 | long_month_names = { 46 | "Januaro", 47 | "Februaro", 48 | "Marto", 49 | "Aprilo", 50 | "Majo", 51 | "Juno", 52 | "Julio", 53 | "Aŭgusto", 54 | "Septembro", 55 | "Oktobro", 56 | "Novembro", 57 | "Decembro", 58 | }, 59 | short_day_names = { 60 | "Dim", 61 | "Lun", 62 | "Mar", 63 | "Mer", 64 | "ĵaŭ", 65 | "Ven", 66 | "Sab", 67 | }, 68 | long_day_names = { 69 | "Dimanĉo", 70 | "Lundo", 71 | "Mardo", 72 | "Merkredo", 73 | "ĵaŭdo", 74 | "Vendredo", 75 | "Sabato", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/ru-RU.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["ru-RU"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "р.", 6 | name = "Рубль", 7 | short_name = "RR", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%p%q%c", 14 | negative_format = "%p%q%c", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%j %F %Y г.", 25 | short_date = "%d.%m.%y", 26 | long_time = "%G:%i:%s", 27 | short_date_time = "%d.%m.%y %G:%i", 28 | short_time = "%G:%i", 29 | long_date_time = "%D, %j %F %Y %G:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Янв", 33 | "Фев", 34 | "Мар", 35 | "Апр", 36 | "Май", 37 | "Июн", 38 | "Июл", 39 | "Авг", 40 | "Сен", 41 | "Окт", 42 | "Ноя", 43 | "Дек", 44 | }, 45 | long_month_names = { 46 | "января", 47 | "февраля", 48 | "марта", 49 | "апреля", 50 | "мая", 51 | "июня", 52 | "июля", 53 | "августа", 54 | "сентября", 55 | "октября", 56 | "ноября", 57 | "декабря", 58 | }, 59 | short_day_names = { 60 | "Вс", 61 | "Пн", 62 | "Вт", 63 | "Ср", 64 | "Чт", 65 | "Пт", 66 | "Сб", 67 | }, 68 | long_day_names = { 69 | "Воскресенье", 70 | "Понедельник", 71 | "Вторник", 72 | "Среда", 73 | "Четверг", 74 | "Пятница", 75 | "Суббота", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/sk-SK.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["sk-SK"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "Sk", 6 | name = "Slovenská koruna", 7 | short_name = "Sk", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%d. %F %Y", 25 | short_date = "%d. %m. %Y", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d. %m. %Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%d. %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mar", 35 | "Apr", 36 | "Máj", 37 | "Jún", 38 | "Júl", 39 | "Aug", 40 | "Sep", 41 | "Okt", 42 | "Nov", 43 | "Dec", 44 | }, 45 | long_month_names = { 46 | "Január", 47 | "Február", 48 | "Marec", 49 | "Apríl", 50 | "Máj", 51 | "Jún", 52 | "Júl", 53 | "August", 54 | "September", 55 | "Október", 56 | "November", 57 | "December", 58 | }, 59 | short_day_names = { 60 | "Ne", 61 | "Po", 62 | "Ut", 63 | "St", 64 | "št", 65 | "Pi", 66 | "So", 67 | }, 68 | long_day_names = { 69 | "Nedeľa", 70 | "Pondelok", 71 | "Utorok", 72 | "Streda", 73 | "štvrtok", 74 | "Piatok", 75 | "Sobota", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/fr-FR.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["fr-FR"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "€", 6 | name = "Euro", 7 | short_name = "EUR", 8 | decimal_symbol = ",", 9 | thousand_separator = " ", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%p%q %c", 14 | negative_format = "%p%q %c", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = " ", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d/%m/%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%l %d %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Fév", 34 | "Mars", 35 | "Avr", 36 | "Mai", 37 | "Juin", 38 | "Juil", 39 | "Août", 40 | "Sep", 41 | "Oct", 42 | "Nov", 43 | "Déc", 44 | }, 45 | long_month_names = { 46 | "Janvier", 47 | "Février", 48 | "Mars", 49 | "Avril", 50 | "Mai", 51 | "Juin", 52 | "Juillet", 53 | "Août", 54 | "Septembre", 55 | "Octobre", 56 | "Novembre", 57 | "Décembre", 58 | }, 59 | short_day_names = { 60 | "Dim", 61 | "Lun", 62 | "Mar", 63 | "Mer", 64 | "Jeu", 65 | "Ven", 66 | "Sam", 67 | }, 68 | long_day_names = { 69 | "Dimanche", 70 | "Lundi", 71 | "Mardi", 72 | "Mercredi", 73 | "Jeudi", 74 | "Vendredi", 75 | "Samedi", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/sr-SR.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["sr-SR"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "DIN", 6 | name = "Dinar", 7 | short_name = "CSD", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%l, %d. %F %Y.", 25 | short_date = "%d.%m.%Y.", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d.%m.%Y. %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%l, %d.%F %Y. %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mar", 35 | "Apr", 36 | "Maj", 37 | "Jun", 38 | "Jul", 39 | "Avg", 40 | "Sep", 41 | "Okt", 42 | "Nov", 43 | "Dec", 44 | }, 45 | long_month_names = { 46 | "Januar", 47 | "Februar", 48 | "Mart", 49 | "April", 50 | "Maj", 51 | "Jun", 52 | "Jul", 53 | "Avgust", 54 | "Septembar", 55 | "Oktobar", 56 | "Novembar", 57 | "Decembar", 58 | }, 59 | short_day_names = { 60 | "Ned", 61 | "Pon", 62 | "Uto", 63 | "Sre", 64 | "če", 65 | "Pet", 66 | "Sub", 67 | }, 68 | long_day_names = { 69 | "Nedelja", 70 | "Ponedjeljak", 71 | "Utorak", 72 | "Sreda", 73 | "četvrtak", 74 | "Petak", 75 | "Subota", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/es-ES.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["es-ES"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "€", 6 | name = "Euro", 7 | short_name = "EUR", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%Y-%m-%d", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%Y-%m-%d %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%l %d %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Ene", 33 | "Feb", 34 | "Mar", 35 | "Abr", 36 | "May", 37 | "Jun", 38 | "Jul", 39 | "Ago", 40 | "Sep", 41 | "Oct", 42 | "Nov", 43 | "Dic", 44 | }, 45 | long_month_names = { 46 | "Enero", 47 | "Febrero", 48 | "Marzo", 49 | "Abril", 50 | "Mayo", 51 | "Junio", 52 | "Julio", 53 | "Agosto", 54 | "Septiembre", 55 | "Octubre", 56 | "Noviembre", 57 | "Diciembre", 58 | }, 59 | short_day_names = { 60 | "Dom.", 61 | "Lun.", 62 | "Mar.", 63 | "Mié.", 64 | "Jue.", 65 | "Vie.", 66 | "Sáb.", 67 | }, 68 | long_day_names = { 69 | "Domingo", 70 | "Lunes", 71 | "Martes", 72 | "Miércoles", 73 | "Jueves", 74 | "Viernes", 75 | "Sábado", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/no-NB.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["no-NB"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "kr", 6 | name = "Norwegian Kroner", 7 | short_name = "NOK", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%d. %F %Y", 25 | short_date = "%d.%m.%Y", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d.%m.%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%d. %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mars", 35 | "April", 36 | "Mai", 37 | "Juni", 38 | "Juli", 39 | "Aug", 40 | "Sep", 41 | "Okt", 42 | "Nov", 43 | "Des", 44 | }, 45 | long_month_names = { 46 | "Januar", 47 | "Februar", 48 | "Mars", 49 | "April", 50 | "Mai", 51 | "Juni", 52 | "Juli", 53 | "August", 54 | "September", 55 | "Oktober", 56 | "November", 57 | "Desember", 58 | }, 59 | short_day_names = { 60 | "Sø.", 61 | "Må.", 62 | "Ty.", 63 | "On.", 64 | "To.", 65 | "Fr.", 66 | "La.", 67 | }, 68 | long_day_names = { 69 | "Søndag", 70 | "Måndag", 71 | "Tysdag", 72 | "Onsdag", 73 | "Torsdag", 74 | "Fredag", 75 | "Laurdag", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/sv-SE.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["sv-SE"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "kr", 6 | name = "Swedish Kronor", 7 | short_name = "SEK", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%d. %F %Y", 25 | short_date = "%d.%m.%Y", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d.%m.%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%d. %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mars", 35 | "April", 36 | "Maj", 37 | "Juni", 38 | "Juli", 39 | "Aug", 40 | "Sep", 41 | "Okt", 42 | "Nov", 43 | "Dec", 44 | }, 45 | long_month_names = { 46 | "Januari", 47 | "Februari", 48 | "Mars", 49 | "April", 50 | "Maj", 51 | "Juni", 52 | "Juli", 53 | "Augusti", 54 | "September", 55 | "Oktober", 56 | "November", 57 | "December", 58 | }, 59 | short_day_names = { 60 | "Sön", 61 | "Mån", 62 | "Tis", 63 | "Ons", 64 | "Tors", 65 | "Fre", 66 | "Lör", 67 | }, 68 | long_day_names = { 69 | "Söndag", 70 | "Måndag", 71 | "Tisdag", 72 | "Onsdag", 73 | "Torsdag", 74 | "Fredag", 75 | "Lördag", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/da-DK.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["da-DK"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "kr", 6 | name = "Danish Kroner", 7 | short_name = "KRR", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%d. %F %Y", 25 | short_date = "%d.%m.%Y", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d.%m.%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%d. %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Marts", 35 | "April", 36 | "Maj", 37 | "Juni", 38 | "Juli", 39 | "Aug", 40 | "Sep", 41 | "Okt", 42 | "Nov", 43 | "Dec", 44 | }, 45 | long_month_names = { 46 | "Januar", 47 | "Februar", 48 | "Marts", 49 | "April", 50 | "Maj", 51 | "Juni", 52 | "Juli", 53 | "August", 54 | "September", 55 | "Oktober", 56 | "November", 57 | "December", 58 | }, 59 | short_day_names = { 60 | "Søn.", 61 | "Man.", 62 | "Tir.", 63 | "Ons.", 64 | "Tor.", 65 | "Fre.", 66 | "Lør.", 67 | }, 68 | long_day_names = { 69 | "Søndag", 70 | "Mandag", 71 | "Tirsdag", 72 | "Onsdag", 73 | "Torsdag", 74 | "Fredag", 75 | "Lørdag", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/id-ID.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["id-ID"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "₹", 6 | name = "Indonesian Rupiah", 7 | short_name = "IDR", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%d/%m/%Y %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mar", 35 | "Apr", 36 | "Mei", 37 | "Jun", 38 | "Jul", 39 | "Agu", 40 | "Sep", 41 | "Okt", 42 | "Nov", 43 | "Des", 44 | }, 45 | long_month_names = { 46 | "Januari", 47 | "Februari", 48 | "Maret", 49 | "April", 50 | "Mei", 51 | "Juni", 52 | "Juli", 53 | "Agustus", 54 | "September", 55 | "Oktober", 56 | "November", 57 | "Desember", 58 | }, 59 | short_day_names = { 60 | "Min", 61 | "Sen", 62 | "Sel", 63 | "Rab", 64 | "Kam", 65 | "Jum", 66 | "Sab", 67 | }, 68 | long_day_names = { 69 | "Minggu", 70 | "Senin", 71 | "Selasa", 72 | "Rabu", 73 | "Kamis", 74 | "Jumat", 75 | "Sabtu", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/it-IT.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["it-IT"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "€", 6 | name = "Euro", 7 | short_name = "EUR", 8 | decimal_symbol = ",", 9 | thousand_separator = " ", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%p%q %c", 14 | negative_format = "%p%q %c", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = " ", 22 | }, 23 | date_time = { 24 | long_date = "%l, %d %F %Y", 25 | short_date = "%d %m %Y", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d/%m/%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%l, %d %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Gen", 33 | "Feb", 34 | "Mar", 35 | "Apr", 36 | "Mag", 37 | "Giu", 38 | "Lug", 39 | "Ago", 40 | "Set", 41 | "Ott", 42 | "Nov", 43 | "Dic", 44 | }, 45 | long_month_names = { 46 | "Gennaio", 47 | "Febbraio", 48 | "Marzo", 49 | "Aprile", 50 | "Maggio", 51 | "Giugno", 52 | "Luglio", 53 | "Agosto", 54 | "Settembre", 55 | "Ottobre", 56 | "Novembre", 57 | "Dicembre", 58 | }, 59 | short_day_names = { 60 | "Dom", 61 | "Lun", 62 | "Mar", 63 | "Mer", 64 | "Gio", 65 | "Ven", 66 | "Sab", 67 | }, 68 | long_day_names = { 69 | "Domenica", 70 | "Lunedì", 71 | "Martedì", 72 | "Mercoledì", 73 | "Giovedì", 74 | "Venerdì", 75 | "Sabato", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/nl-NL.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["nl-NL"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "€", 6 | name = "Euro", 7 | short_name = "EUR", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%d/%m/%Y %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mrt", 35 | "Apr", 36 | "Mei", 37 | "Jun", 38 | "Jul", 39 | "Aug", 40 | "Sep", 41 | "Okt", 42 | "Nov", 43 | "Dec", 44 | }, 45 | long_month_names = { 46 | "Januari", 47 | "Februari", 48 | "Maart", 49 | "April", 50 | "Mei", 51 | "Juni", 52 | "Juli", 53 | "Augustus", 54 | "September", 55 | "Oktober", 56 | "November", 57 | "December", 58 | }, 59 | short_day_names = { 60 | "Zon", 61 | "Ma", 62 | "Di", 63 | "Woe", 64 | "Do", 65 | "Vr", 66 | "Zat", 67 | }, 68 | long_day_names = { 69 | "Zondag", 70 | "Maandag", 71 | "Dinsdag", 72 | "Woensdag", 73 | "Donderdag", 74 | "Vrijdag", 75 | "Zaterdag", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/en-US.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["en-US"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "$", 6 | name = "US Dollar", 7 | short_name = "USD", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%d/%m/%Y %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mar", 35 | "Apr", 36 | "May", 37 | "Jun", 38 | "Jul", 39 | "Aug", 40 | "Sep", 41 | "Oct", 42 | "Nov", 43 | "Dec", 44 | }, 45 | long_month_names = { 46 | "January", 47 | "February", 48 | "March", 49 | "April", 50 | "May", 51 | "Jun", 52 | "July", 53 | "August", 54 | "September", 55 | "October", 56 | "November", 57 | "December", 58 | }, 59 | short_day_names = { 60 | "Sun", 61 | "Mon", 62 | "Tue", 63 | "Wed", 64 | "Thu", 65 | "Fri", 66 | "Sat", 67 | }, 68 | long_day_names = { 69 | "Sunday", 70 | "Monday", 71 | "Tuesday", 72 | "Wednesday", 73 | "Thursday", 74 | "Friday", 75 | "Saturday", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/hr-HR.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["hr-HR"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "kn", 6 | name = "Kuna", 7 | short_name = "HRK", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%p%q %c", 14 | negative_format = "%p%q %c", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%l, %d. %F %Y.", 25 | short_date = "%d.%m.%Y", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d.%m.%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%l, %d. %F %Y. %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Sij", 33 | "Velj", 34 | "Ožu", 35 | "Tra", 36 | "Svi", 37 | "Lip", 38 | "Srp", 39 | "Kol", 40 | "Ruj", 41 | "Lis", 42 | "Stu", 43 | "Pro", 44 | }, 45 | long_month_names = { 46 | "Siječanj", 47 | "Veljača", 48 | "Ožujak", 49 | "Travanj", 50 | "Svibanj", 51 | "Lipanj", 52 | "Srpanj", 53 | "Kolovoz", 54 | "Rujan", 55 | "Listopad", 56 | "Studeni", 57 | "Prosinac", 58 | }, 59 | short_day_names = { 60 | "Ned", 61 | "Pon", 62 | "Uto", 63 | "Sri", 64 | "čet", 65 | "Pet", 66 | "Sub", 67 | }, 68 | long_day_names = { 69 | "Nedjelja", 70 | "Ponedjeljak", 71 | "Utorak", 72 | "Srijeda", 73 | "četvrtak", 74 | "Petak", 75 | "Subota", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/hu-HU.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["hu-HU"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "Ft", 6 | name = "Hungarian Forint", 7 | short_name = "HUF", 8 | decimal_symbol = ",", 9 | thousand_separator = " ", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%p%q %c", 14 | negative_format = "%p%q %c", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = " ", 22 | }, 23 | date_time = { 24 | long_date = "%Y. %F %d. %l", 25 | short_date = "%Y. %m. %d.", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%Y.%m.%d %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%Y. %F %d. %l, %H:%i", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Már", 35 | "ápr", 36 | "Máj", 37 | "Jún", 38 | "Júl", 39 | "Aug", 40 | "Szep", 41 | "Okt", 42 | "Nov", 43 | "Dec", 44 | }, 45 | long_month_names = { 46 | "Január", 47 | "Február", 48 | "Március", 49 | "április", 50 | "Május", 51 | "Június", 52 | "Július", 53 | "Augusztus", 54 | "Szeptember", 55 | "Október", 56 | "November", 57 | "December", 58 | }, 59 | short_day_names = { 60 | "V", 61 | "H", 62 | "K", 63 | "Sze", 64 | "Cs", 65 | "P", 66 | "Szo", 67 | }, 68 | long_day_names = { 69 | "Vasárnap", 70 | "Hétfő", 71 | "Kedd", 72 | "Szerda", 73 | "Csütörtök", 74 | "Péntek", 75 | "Szombat", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/en-CA.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["en-CA"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "$", 6 | name = "Canadian Dollar", 7 | short_name = "CAD", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%d/%m/%Y %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mar", 35 | "Apr", 36 | "May", 37 | "Jun", 38 | "Jul", 39 | "Aug", 40 | "Sep", 41 | "Oct", 42 | "Nov", 43 | "Dec", 44 | }, 45 | long_month_names = { 46 | "January", 47 | "February", 48 | "March", 49 | "April", 50 | "May", 51 | "Jun", 52 | "July", 53 | "August", 54 | "September", 55 | "October", 56 | "November", 57 | "December", 58 | }, 59 | short_day_names = { 60 | "Sun", 61 | "Mon", 62 | "Tue", 63 | "Wed", 64 | "Thu", 65 | "Fri", 66 | "Sat", 67 | }, 68 | long_day_names = { 69 | "Sunday", 70 | "Monday", 71 | "Tuesday", 72 | "Wednesday", 73 | "Thursday", 74 | "Friday", 75 | "Saturday", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/en-NZ.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["en-NZ"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "$", 6 | name = "Zealand Dollar", 7 | short_name = "NZD", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%d/%m/%Y %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mar", 35 | "Apr", 36 | "May", 37 | "Jun", 38 | "Jul", 39 | "Aug", 40 | "Sep", 41 | "Oct", 42 | "Nov", 43 | "Dec", 44 | }, 45 | long_month_names = { 46 | "January", 47 | "February", 48 | "March", 49 | "April", 50 | "May", 51 | "Jun", 52 | "July", 53 | "August", 54 | "September", 55 | "October", 56 | "November", 57 | "December", 58 | }, 59 | short_day_names = { 60 | "Sun", 61 | "Mon", 62 | "Tue", 63 | "Wed", 64 | "Thu", 65 | "Fri", 66 | "Sat", 67 | }, 68 | long_day_names = { 69 | "Sunday", 70 | "Monday", 71 | "Tuesday", 72 | "Wednesday", 73 | "Thursday", 74 | "Friday", 75 | "Saturday", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/en-UK.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["en-UK"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "£", 6 | name = "British Pound", 7 | short_name = "GBP", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%d/%m/%Y %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mar", 35 | "Apr", 36 | "May", 37 | "Jun", 38 | "Jul", 39 | "Aug", 40 | "Sep", 41 | "Oct", 42 | "Nov", 43 | "Dec", 44 | }, 45 | long_month_names = { 46 | "January", 47 | "February", 48 | "March", 49 | "April", 50 | "May", 51 | "Jun", 52 | "July", 53 | "August", 54 | "September", 55 | "October", 56 | "November", 57 | "December", 58 | }, 59 | short_day_names = { 60 | "Sun", 61 | "Mon", 62 | "Tue", 63 | "Wed", 64 | "Thu", 65 | "Fri", 66 | "Sat", 67 | }, 68 | long_day_names = { 69 | "Sunday", 70 | "Monday", 71 | "Tuesday", 72 | "Wednesday", 73 | "Thursday", 74 | "Friday", 75 | "Saturday", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/hi-IN.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["hi-IN"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "₹", 6 | name = "Indian Rupee", 7 | short_name = "INR", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%d/%m/%Y %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "jan", 33 | "feb", 34 | "mar", 35 | "apr", 36 | "may", 37 | "jun", 38 | "jul", 39 | "aug", 40 | "sep", 41 | "oct", 42 | "nov", 43 | "dec", 44 | }, 45 | long_month_names = { 46 | "january", 47 | "february", 48 | "march", 49 | "april", 50 | "may", 51 | "jun", 52 | "july", 53 | "august", 54 | "september", 55 | "october", 56 | "november", 57 | "december", 58 | }, 59 | short_day_names = { 60 | "sun", 61 | "mon", 62 | "tue", 63 | "wed", 64 | "thu", 65 | "fri", 66 | "sat", 67 | }, 68 | long_day_names = { 69 | "sunday", 70 | "monday", 71 | "tuesday", 72 | "wednesday", 73 | "thursday", 74 | "friday", 75 | "saturday", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/pl-PL.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["pl-PL"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "zł", 6 | name = "Polski złoty", 7 | short_name = "PLN", 8 | decimal_symbol = ",", 9 | thousand_separator = " ", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%p%q %c", 14 | negative_format = "%p%q %c", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = " ", 22 | }, 23 | date_time = { 24 | long_date = "%l, %j %F %Y", 25 | short_date = "%d.%m.%Y", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%d.%m.%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%l, %j %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Sty", 33 | "Lut", 34 | "Mar", 35 | "Kwi", 36 | "Maj", 37 | "Cze", 38 | "Lip", 39 | "Sie", 40 | "Wrz", 41 | "Paź", 42 | "Lis", 43 | "Gru", 44 | }, 45 | long_month_names = { 46 | "Styczeń", 47 | "Luty", 48 | "Marzec", 49 | "Kwiecień", 50 | "Maj", 51 | "Czerwiec", 52 | "Lipiec", 53 | "Sierpień", 54 | "Wrzesień", 55 | "Październik", 56 | "Listopad", 57 | "Grudzień", 58 | }, 59 | short_day_names = { 60 | "N", 61 | "Pon", 62 | "Wt", 63 | "Śr", 64 | "Czw", 65 | "Pt", 66 | "So", 67 | }, 68 | long_day_names = { 69 | "Niedziela", 70 | "Poniedziałek", 71 | "Wtorek", 72 | "Środa", 73 | "Czwartek", 74 | "Piątek", 75 | "Sobota", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/uk-UA.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["uk-UA"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "грн.", 6 | name = "Гривня", 7 | short_name = "UAH", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%d/%m/%Y %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "Січ", 33 | "Лют", 34 | "Бер", 35 | "Кві", 36 | "Тра", 37 | "Чер", 38 | "Лип", 39 | "Сер", 40 | "Вер", 41 | "Жов", 42 | "Лис", 43 | "Гру", 44 | }, 45 | long_month_names = { 46 | "Січень", 47 | "Лютий", 48 | "Березень", 49 | "Квітень", 50 | "Травень", 51 | "Червень", 52 | "Липень", 53 | "Серпень", 54 | "Вересень", 55 | "Жовтень", 56 | "Листопад", 57 | "Грудень", 58 | }, 59 | short_day_names = { 60 | "Нд", 61 | "Пн", 62 | "Вт", 63 | "Ср", 64 | "Чт", 65 | "Пт", 66 | "Сб", 67 | }, 68 | long_day_names = { 69 | "Неділя", 70 | "Понеділок", 71 | "Вівторок", 72 | "Середа", 73 | "Четвер", 74 | "П'ятниця", 75 | "Субота", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/en-AU.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["en-AU"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "$", 6 | name = "Australian Dollar", 7 | short_name = "AUD", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ".", 21 | thousand_separator = ",", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%d/%m/%Y %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "Jan", 33 | "Feb", 34 | "Mar", 35 | "Apr", 36 | "May", 37 | "Jun", 38 | "Jul", 39 | "Aug", 40 | "Sep", 41 | "Oct", 42 | "Nov", 43 | "Dec", 44 | }, 45 | long_month_names = { 46 | "January", 47 | "February", 48 | "March", 49 | "April", 50 | "May", 51 | "Jun", 52 | "July", 53 | "August", 54 | "September", 55 | "October", 56 | "November", 57 | "December", 58 | }, 59 | short_day_names = { 60 | "Sun", 61 | "Mon", 62 | "Tue", 63 | "Wed", 64 | "Thu", 65 | "Fri", 66 | "Sat", 67 | }, 68 | long_day_names = { 69 | "Sunday", 70 | "Monday", 71 | "Tuesday", 72 | "Wednesday", 73 | "Thursday", 74 | "Friday", 75 | "Saturday", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/el-GR.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["el-GR"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "€", 6 | name = "Euro", 7 | short_name = "EUR", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%d/%m/%Y %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "Ιαν", 33 | "Φεβ", 34 | "Μαρ", 35 | "Απρ", 36 | "Μαϊ", 37 | "Ιουν", 38 | "Ιουλ", 39 | "Αυγ", 40 | "Σεπ", 41 | "Οκτ", 42 | "Nοε", 43 | "Δεκ", 44 | }, 45 | long_month_names = { 46 | "Ιανουαρίου", 47 | "Φεβρουαρίου", 48 | "Μαρτίου", 49 | "Απριλίου", 50 | "Μαΐου", 51 | "Ιουνίου", 52 | "Ιουλίου", 53 | "Αυγούστου", 54 | "Σεπτεμβρίου", 55 | "Οκτωβρίου", 56 | "Νοεμβρίου", 57 | "Δεκεμβρίου", 58 | }, 59 | short_day_names = { 60 | "Κυρ", 61 | "Δευ", 62 | "Τρι", 63 | "Τετ", 64 | "Πεμ", 65 | "Παρ", 66 | "Σαβ", 67 | }, 68 | long_day_names = { 69 | "Κυριακή", 70 | "Δευτέρα", 71 | "Τρίτη", 72 | "Τετάρτη", 73 | "Πέμπτη", 74 | "Παρασκευή", 75 | "Σάββατο", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/fi-FI.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["fi-FI"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "€", 6 | name = "Euro", 7 | short_name = "EUR", 8 | decimal_symbol = ",", 9 | thousand_separator = ".", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c%p%q", 14 | negative_format = "%c%p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = ".", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%Y-%m-%d", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%j.%n.%Y %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%l %j. %F %Y %H:%i:%s", 30 | }, 31 | short_month_names = { 32 | "Tammi", 33 | "Helmi", 34 | "Maalis", 35 | "Huhti", 36 | "Touko", 37 | "Kesä", 38 | "Heinä", 39 | "Elo", 40 | "Syys", 41 | "Loka", 42 | "Marras", 43 | "Joulu", 44 | }, 45 | long_month_names = { 46 | "Tammikuu", 47 | "Helmikuu", 48 | "Maaliskuu", 49 | "Huhtikuu", 50 | "Toukokuu", 51 | "Kesäkuu", 52 | "Heinäkuu", 53 | "Elokuu", 54 | "Syyskuu", 55 | "Lokakuu", 56 | "Marraskuu", 57 | "Joulukuu", 58 | }, 59 | short_day_names = { 60 | "Su", 61 | "Ma", 62 | "Ti", 63 | "Ke", 64 | "To", 65 | "Pe", 66 | "La", 67 | }, 68 | long_day_names = { 69 | "Sunnuntai", 70 | "Maanantai", 71 | "Tiistai", 72 | "Keskiviikko", 73 | "Torstai", 74 | "Perjantai", 75 | "Lauantai", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/ar-SA.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["ar-SA"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "MAD", 6 | name = "Dirham Marocain", 7 | short_name = "MAD", 8 | decimal_symbol = ".", 9 | thousand_separator = ",", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%c %p%q", 14 | negative_format = "%c %p%q", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = " ", 22 | }, 23 | date_time = { 24 | long_date = "%l %d %F %Y", 25 | short_date = "%d/%m/%Y", 26 | long_time = "%g:%i:%s %a", 27 | short_date_time = "%d/%m/%Y %g:%i %a", 28 | short_time = "%g:%i %a", 29 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 30 | }, 31 | short_month_names = { 32 | "يناير", 33 | "فبراير", 34 | "مارس", 35 | "أبريل", 36 | "مايو", 37 | "يونيو", 38 | "يوليو", 39 | "أغسطس", 40 | "سبتمبر", 41 | "أكتوبر", 42 | "نوفمبر", 43 | "ديسمبر", 44 | }, 45 | long_month_names = { 46 | "يناير", 47 | "فبراير", 48 | "مارس", 49 | "أبريل", 50 | "مايو", 51 | "يونيو", 52 | "يوليو", 53 | "أغسطس", 54 | "سبتمبر", 55 | "أكتوبر", 56 | "نوفمبر", 57 | "ديسمبر", 58 | }, 59 | short_day_names = { 60 | "الأحد", 61 | "الاثنين", 62 | "الثلاثاء", 63 | "الأربعاء", 64 | "الخميس", 65 | "الجمعة", 66 | "السبت", 67 | }, 68 | long_day_names = { 69 | "الأحد", 70 | "الاثنين", 71 | "الثلاثاء", 72 | "الأربعاء", 73 | "الخميس", 74 | "الجمعة", 75 | "السبت", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /locales/he-IL.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["he-IL"] = { 3 | _formats = { 4 | currency = { 5 | symbol = "€", 6 | name = "Euro", 7 | short_name = "EUR", 8 | decimal_symbol = ",", 9 | thousand_separator = " ", 10 | fract_digits = 2, 11 | positive_symbol = "", 12 | negative_symbol = "-", 13 | positive_format = "%p%q %c", 14 | negative_format = "%p%q %c", 15 | }, 16 | number = { 17 | fract_digits = 2, 18 | positive_symbol = "", 19 | negative_symbol = "-", 20 | decimal_symbol = ",", 21 | thousand_separator = " ", 22 | }, 23 | date_time = { 24 | long_date = "%Y. %F %d. %l", 25 | short_date = "%Y. %m. %d.", 26 | long_time = "%H:%i:%s", 27 | short_date_time = "%Y.%m.%d %H:%i", 28 | short_time = "%H:%i", 29 | long_date_time = "%Y. %F %d. %l, %H:%i", 30 | }, 31 | short_month_names = { 32 | "ינואר", 33 | "פבואר", 34 | "מרץ", 35 | "אפריל", 36 | "מאי", 37 | "יוני", 38 | "יולי", 39 | "נִשׂגָב", 40 | "ספטמבר", 41 | "אוקטובר", 42 | "נובמבר", 43 | "דצמבר", 44 | }, 45 | long_month_names = { 46 | "ינואר", 47 | "פבואר", 48 | "מרץ", 49 | "אפריל", 50 | "מאי", 51 | "יוני", 52 | "יולי", 53 | "נִשׂגָב", 54 | "ספטמבר", 55 | "אוקטובר", 56 | "נובמבר", 57 | "דצמבר", 58 | }, 59 | short_day_names = { 60 | "יום ראשון", 61 | "יום שני", 62 | "יום שלישי", 63 | "יום רביעי", 64 | "יום חמישי", 65 | "יום שישי", 66 | "יום שבת", 67 | }, 68 | long_day_names = { 69 | "יום ראשון", 70 | "יום שני", 71 | "יום שלישי", 72 | "יום רביעי", 73 | "יום חמישי", 74 | "יום שישי", 75 | "יום שבת", 76 | }, 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /rockspecs/smiti18n-0.9.4-1.rockspec: -------------------------------------------------------------------------------- 1 | local _version = "0.9.4" 2 | local _revision = "1" 3 | 4 | rockspec_format = "3.0" 5 | package = "smiti18n" 6 | version = _version .. "-" .. _revision 7 | source = { 8 | url = ("https://github.com/Oval-Tutu/smiti18n/archive/%s.tar.gz"):format(_version), 9 | dir = ("smiti18n-%s"):format(_version) 10 | } 11 | description = { 12 | summary = "A very complete internationalization library for Lua with LÖVE support", 13 | detailed = [[ 14 | smiti18n (pronounced smitten) is a powerful internationalization (i18n) library that helps you create multilingual applications in Lua and LÖVE. 15 | 16 | **Core Features:** 17 | - Smart file-based loading & fallbacks 18 | - Rich text interpolation & pluralization 19 | - Locale-aware formatting for numbers, dates and currency 20 | - Built for LÖVE game engine 21 | 22 | **Rich Game Content:** 23 | - Complex dialogue support: 24 | - Branching conversations 25 | - Character-specific translations 26 | - Context-aware responses 27 | - 53 locales, 650+ game-specific phrases 28 | - 36 regional number formats 29 | 30 | An intuitive API for managing translations forked from i18n.lua by Enrique García Cota incorporating a collection of community contributions. 31 | The number, date and time formatting has been ported from Babel. 32 | Includes translations from PolyglotGamedev. 33 | Significantly expanded test coverage and documentation. 34 | 35 | Requirements 36 | - Lua 5.1-5.4 or LuaJIT 2.0-2.1 37 | - LÖVE 11.0+ (optional) 38 | ]], 39 | labels = { "i18n", "love" }, 40 | homepage = "https://github.com/Oval-Tutu/smiti18n", 41 | license = "MIT" 42 | } 43 | dependencies = { 44 | "lua >= 5.1" 45 | } 46 | build = { 47 | type = "builtin", 48 | modules = { 49 | ["smiti18n.format"] = "smiti18n/format.lua", 50 | ["smiti18n.init"] = "smiti18n/init.lua", 51 | ["smiti18n.interpolate"] = "smiti18n/interpolate.lua", 52 | ["smiti18n.plural"] = "smiti18n/plural.lua", 53 | ["smiti18n.variants"] = "smiti18n/variants.lua" 54 | }, 55 | copy_directories = { 56 | "locales" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /rockspecs/smiti18n-0.9.5-1.rockspec: -------------------------------------------------------------------------------- 1 | local _version = "0.9.5" 2 | local _revision = "1" 3 | 4 | rockspec_format = "3.0" 5 | package = "smiti18n" 6 | version = _version .. "-" .. _revision 7 | source = { 8 | url = ("https://github.com/Oval-Tutu/smiti18n/archive/%s.tar.gz"):format(_version), 9 | dir = ("smiti18n-%s"):format(_version) 10 | } 11 | description = { 12 | summary = "A very complete internationalization library for Lua with LÖVE support", 13 | detailed = [[ 14 | smiti18n (pronounced smitten) is a powerful internationalization (i18n) library that helps you create multilingual applications in Lua and LÖVE. 15 | 16 | **Core Features:** 17 | - Smart file-based loading & fallbacks 18 | - Rich text interpolation & pluralization 19 | - Locale-aware formatting for numbers, dates and currency 20 | - Built for LÖVE game engine 21 | 22 | **Rich Game Content:** 23 | - Complex dialogue support: 24 | - Branching conversations 25 | - Character-specific translations 26 | - Context-aware responses 27 | - 53 locales, 650+ game-specific phrases 28 | - 36 regional number formats 29 | 30 | An intuitive API for managing translations forked from i18n.lua by Enrique García Cota incorporating a collection of community contributions. 31 | The number, date and time formatting has been ported from Babel. 32 | Includes translations from PolyglotGamedev. 33 | Significantly expanded test coverage and documentation. 34 | 35 | Requirements 36 | - Lua 5.1-5.4 or LuaJIT 2.0-2.1 37 | - LÖVE 11.0+ (optional) 38 | ]], 39 | labels = { "i18n", "love" }, 40 | homepage = "https://github.com/Oval-Tutu/smiti18n", 41 | license = "MIT" 42 | } 43 | dependencies = { 44 | "lua >= 5.1" 45 | } 46 | build = { 47 | type = "builtin", 48 | modules = { 49 | ["smiti18n.format"] = "smiti18n/format.lua", 50 | ["smiti18n.init"] = "smiti18n/init.lua", 51 | ["smiti18n.interpolate"] = "smiti18n/interpolate.lua", 52 | ["smiti18n.plural"] = "smiti18n/plural.lua", 53 | ["smiti18n.variants"] = "smiti18n/variants.lua" 54 | }, 55 | copy_directories = { 56 | "locales" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /spec/data/en-UK.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["en-UK"] = { 3 | _formats = { 4 | number = { 5 | positive_symbol = "", 6 | negative_symbol = "-", 7 | decimal_symbol = ".", 8 | thousand_separator = ",", 9 | fract_digits = "2", 10 | }, 11 | currency = { 12 | short_name = "GBP", 13 | decimal_symbol = ".", 14 | thousand_separator = ",", 15 | fract_digits = "2", 16 | positive_symbol = "", 17 | negative_symbol = "-", 18 | positive_format = "%c %p%q", 19 | negative_format = "%c %p%q", 20 | symbol = "£", 21 | name = "British Pound", 22 | }, 23 | short_day_names = { 24 | "Sun", 25 | "Mon", 26 | "Tue", 27 | "Wed", 28 | "Thu", 29 | "Fri", 30 | "Sat" 31 | }, 32 | date_time = { 33 | short_date_time = "%d/%m/%Y %g:%i %a", 34 | short_time = "%g:%i %a", 35 | short_date = "%d/%m/%Y", 36 | long_date_time = "%l %d %F %Y %g:%i:%s %a", 37 | long_date = "%l %d %F %Y", 38 | long_time = "%g:%i:%s %a", 39 | }, 40 | long_day_names = { 41 | "Sunday", 42 | "Monday", 43 | "Tuesday", 44 | "Wednesday", 45 | "Thursday", 46 | "Friday", 47 | "Saturday" 48 | }, 49 | short_month_names = { 50 | "Jan", 51 | "Feb", 52 | "Mar", 53 | "Apr", 54 | "May", 55 | "Jun", 56 | "Jul", 57 | "Aug", 58 | "Sep", 59 | "Oct", 60 | "Nov", 61 | "Dec" 62 | }, 63 | long_month_names = { 64 | "January", 65 | "February", 66 | "March", 67 | "April", 68 | "May", 69 | "Jun", 70 | "July", 71 | "August", 72 | "September", 73 | "October", 74 | "November", 75 | "December" 76 | }, 77 | }, 78 | ["hello"] = 'Hello!', 79 | ["balance"] = 'Your account balance is %{value}.', 80 | ["array"] = {"one", "two", "three"}, 81 | }, 82 | } 83 | -------------------------------------------------------------------------------- /smiti18n/interpolate.lua: -------------------------------------------------------------------------------- 1 | local unpack = unpack or table.unpack -- lua 5.2 compat 2 | 3 | local interpolate = {} 4 | 5 | local FORMAT_CHARS = { c=1, d=1, E=1, e=1, f=1, g=1, G=1, i=1, o=1, u=1, X=1, x=1, s=1, q=1, ['%']=1 } 6 | 7 | local fieldPattern = "(.?)%%{%s*(.-)%s*}" 8 | local valuePattern = "(.?)%%<%s*(.-)%s*>%.([cdEefgGiouXxsq])" 9 | function interpolate.getInterpolationKey(string, variables) 10 | for previous, key in string:gmatch(fieldPattern) do 11 | if previous ~= "%" and variables[key] then 12 | return key 13 | end 14 | end 15 | 16 | for previous, key in string:gmatch(valuePattern) do 17 | if previous ~= "%" and variables[key] then 18 | return key 19 | end 20 | end 21 | end 22 | 23 | -- matches a string of type %{age} 24 | local function interpolateValue(string, variables) 25 | return string:gsub(fieldPattern, 26 | function (previous, key) 27 | if previous == "%" then 28 | return 29 | else 30 | return previous .. tostring(variables[key]) 31 | end 32 | end) 33 | end 34 | 35 | -- matches a string of type %.d 36 | local function interpolateField(string, variables) 37 | return string:gsub(valuePattern, 38 | function (previous, key, format) 39 | if previous == "%" then 40 | return 41 | else 42 | return previous .. string.format("%" .. format, variables[key] or "nil") 43 | end 44 | end) 45 | end 46 | 47 | local function escapePercentages(string) 48 | return string:gsub("(%%)(.?)", function(_, char) 49 | if FORMAT_CHARS[char] then 50 | return "%" .. char 51 | else 52 | return "%%" .. char 53 | end 54 | end) 55 | end 56 | 57 | local function unescapePercentages(string) 58 | return string:gsub("(%%%%)(.?)", "%%") 59 | end 60 | 61 | local function interpolateString(pattern, variables) 62 | variables = variables or {} 63 | local result = pattern 64 | result = interpolateValue(result, variables) 65 | result = interpolateField(result, variables) 66 | result = escapePercentages(result) 67 | result = string.format(result, unpack(variables)) 68 | result = unescapePercentages(result) 69 | return result 70 | end 71 | 72 | setmetatable(interpolate, {__call = function(_, ...) return interpolateString(...) end}) 73 | 74 | return interpolate 75 | -------------------------------------------------------------------------------- /spec/test_variants.lua: -------------------------------------------------------------------------------- 1 | local variants = require 'smiti18n.variants' 2 | 3 | describe("smiti18n.variants", function() 4 | it("is a table", function() 5 | assert.equal('table', type(variants)) 6 | end) 7 | 8 | describe(".ancestry", function() 9 | it("returns just the locale for simple locales", function() 10 | assert.same(variants.ancestry('en'), {'en'}) 11 | end) 12 | 13 | it("returns self and parents for composite locales", function() 14 | assert.same(variants.ancestry('en-US-texas'), {'en-US-texas', 'en-US', 'en'}) 15 | end) 16 | end) 17 | 18 | describe(".isParent", function() 19 | it("works as expected", function() 20 | assert.is_true(variants.isParent('en', 'en-US')) 21 | assert.is_false(variants.isParent('en-US', 'en')) 22 | assert.is_false(variants.isParent('en', 'fr')) 23 | assert.is_false(variants.isParent('en', 'english')) 24 | assert.is_false(variants.isParent('en', 'en')) 25 | end) 26 | end) 27 | 28 | describe(".root", function() 29 | it("returns just the locale for simple locales", function() 30 | assert.equal('en', variants.root('en')) 31 | end) 32 | it("returns the root for composite locales", function() 33 | assert.equal('en', variants.root('en-US')) 34 | end) 35 | end) 36 | 37 | describe(".fallbacks", function() 38 | describe("when given locales of the same ancestry", function() 39 | it("returns the locale ancestry if given exactly the same locale twice", function() 40 | assert.same(variants.fallbacks({'en-US','en-US'}), {'en-US', 'en'}) 41 | end) 42 | it("returns the locale ancestry if fallbackLocale is parent of locale", function() 43 | assert.same(variants.fallbacks({'en-US','en'}), {'en-US', 'en'}) 44 | end) 45 | end) 46 | describe("when given two different locales", function() 47 | it("returns the first locale first, followed by the fallback locale ancestry", function() 48 | assert.same(variants.fallbacks({'fr-CA', 'en-US'}), {'fr-CA', 'fr', 'en-US', 'en'}) 49 | end) 50 | end) 51 | describe("when given just one locales", function() 52 | it("It just returns the one ancestry", function() 53 | assert.same(variants.fallbacks({'fr-CA'}), {'fr-CA', 'fr'}) 54 | end) 55 | end) 56 | describe("when given three different locales", function() 57 | it("returns the locale ancestries in order", function() 58 | assert.same(variants.fallbacks({'fr-CA', 'es-ES', 'en-US'}), {'fr-CA', 'fr', 'es-ES', 'es', 'en-US', 'en'}) 59 | end) 60 | end) 61 | end) 62 | end) 63 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 🏷️ 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v?[0-9]+.[0-9]+.[0-9]+*" 7 | workflow_dispatch: 8 | inputs: 9 | tag: 10 | description: "The existing tag to publish" 11 | type: "string" 12 | required: true 13 | 14 | env: 15 | VERSION: ${{ github.event.inputs.tag || github.ref_name }} 16 | 17 | jobs: 18 | version-check: 19 | if: github.event_name == 'push' || github.event.inputs.tag != '' 20 | name: "Check versions ⚖️" 21 | runs-on: ubuntu-22.04 22 | steps: 23 | - uses: actions/checkout@v5 24 | with: 25 | fetch-depth: 0 26 | - name: "Compare Rockspec and Git versions 🟰" 27 | run: | 28 | if [ ! -d "rockspecs" ]; then 29 | echo "ERROR: rockspecs directory not found" 30 | exit 1 31 | fi 32 | VERSION=$(echo ${{ env.VERSION }} | sed 's/^v//') 33 | ROCKSPEC="rockspecs/smiti18n-${VERSION}-1.rockspec" 34 | if [ ! -e "${ROCKSPEC}" ]; then 35 | echo "ERROR: No rockspec found for version ${VERSION}" 36 | echo "Expected: ${ROCKSPEC}" 37 | ls -la rockspecs/*.rockspec 38 | exit 1 39 | fi 40 | SRC_VERSION=$(cut -d"'" -f 2 smiti18n/version.lua | sed 's/"//g') 41 | if [ "${VERSION}" != "${SRC_VERSION}" ]; then 42 | echo "ERROR: Version mismatch between tag and source" 43 | echo "Tag: ${VERSION}" 44 | echo "Lua: ${SRC_VERSION}" 45 | exit 1 46 | fi 47 | 48 | publish-release: 49 | needs: [version-check] 50 | name: "Publish Release 📤️" 51 | runs-on: ubuntu-22.04 52 | steps: 53 | - uses: actions/checkout@v5 54 | - name: "Publish release" 55 | env: 56 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 57 | run: | 58 | VERSION=$(echo ${{ env.VERSION }} | sed 's/^v//') 59 | gh release create "${VERSION}" \ 60 | --draft=false \ 61 | --title "Release ${VERSION}" \ 62 | --generate-notes 63 | 64 | publish-rockspec: 65 | needs: [publish-release] 66 | name: "Publish Rockspec 🪨" 67 | runs-on: ubuntu-22.04 68 | steps: 69 | - uses: actions/checkout@v5 70 | - name: "Setup Lua" 71 | uses: jkl1337/gh-actions-lua@v11 72 | with: 73 | luaVersion: "5.4" 74 | - name: "Setup LuaRocks" 75 | uses: jkl1337/gh-actions-luarocks@v5 76 | with: 77 | luaRocksVersion: "3.11.1" 78 | - name: "Upload rockspec" 79 | env: 80 | LUAROCKS_API_KEY: ${{ secrets.LUAROCKS_API_KEY }} 81 | run: | 82 | VERSION=$(echo ${{ env.VERSION }} | sed 's/^v//') 83 | luarocks upload "rockspecs/smiti18n-${VERSION}-1.rockspec" --api-key=${LUAROCKS_API_KEY} 84 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Test 🧪 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | paths: 7 | - 'locales/**' 8 | - 'smiti18n/**' 9 | - 'spec/**' 10 | pull_request: 11 | branches: [ master ] 12 | workflow_dispatch: 13 | 14 | jobs: 15 | test: 16 | name: Test and check ️🔎 17 | runs-on: ubuntu-22.04 18 | strategy: 19 | matrix: 20 | lua-version: ${{ github.actor == 'nektos/act' && fromJSON('["5.1"]') || fromJSON('["5.1", "5.2", "5.3", "5.4", "luajit"]') }} 21 | steps: 22 | - uses: actions/checkout@v5 23 | - uses: jkl1337/gh-actions-lua@v11 24 | with: 25 | luaVersion: "${{ matrix.lua-version }}" 26 | - uses: jkl1337/gh-actions-luarocks@v5 27 | with: 28 | luaRocksVersion: "3.11.1" 29 | - name: Install dependencies 30 | run: | 31 | luarocks install busted 32 | luarocks install cluacov 33 | luarocks install inspect 34 | luarocks install luacheck 35 | luarocks install luacov 36 | - name: Run checks and tests 37 | run: | 38 | luacheck --no-unused-args --std max+busted locales smiti18n spec 39 | busted 40 | - name: Generate and show coverage report 41 | run: | 42 | luacov 43 | cat luacov.report.out 44 | cp luacov.report.out luacov-${{ matrix.lua-version }}.txt 45 | - name: Upload coverage report 46 | uses: actions/upload-artifact@v4 47 | with: 48 | name: luacov-${{ matrix.lua-version }}.txt 49 | path: luacov-${{ matrix.lua-version }}.txt 50 | - name: Create coverage table script 51 | run: | 52 | cat > coverage-table.lua << 'EOF' 53 | local output = { 54 | string.format("# Test Coverage Summary - %s\n", os.getenv("LUA_VERSION")), 55 | "| File | Hits | Missed | Coverage |\n", 56 | "|------|------|---------|----------|\n" 57 | } 58 | 59 | local rows = {} 60 | local total_line = "" 61 | for line in io.lines("luacov.report.out") do 62 | local file, hits, missed, coverage = line:match("^([%w%p]+)%s+(%d+)%s+(%d+)%s+([%d%.]+)%%") 63 | if file then 64 | local row = string.format("| %s | %s | %s | %s%% |\n", file, hits, missed, coverage) 65 | if file == "Total" then 66 | total_line = row 67 | else 68 | table.insert(rows, row) 69 | end 70 | end 71 | end 72 | 73 | table.sort(rows) 74 | for _, row in ipairs(rows) do 75 | table.insert(output, row) 76 | end 77 | table.insert(output, total_line) 78 | io.open(os.getenv("GITHUB_STEP_SUMMARY"), "w"):write(table.concat(output)) 79 | EOF 80 | chmod +x coverage-table.lua 81 | - name: Create coverage summary 82 | env: 83 | LUA_VERSION: ${{ matrix.lua-version }} 84 | run: lua coverage-table.lua 85 | -------------------------------------------------------------------------------- /spec/test_plural.lua: -------------------------------------------------------------------------------- 1 | local plural = require 'smiti18n.plural' 2 | 3 | describe('smiti18n.plural', function() 4 | before_each(plural.reset) 5 | 6 | it("exists", function() 7 | assert.equal('table', type(plural)) 8 | end) 9 | 10 | describe('plural.get', function() 11 | 12 | local function test_get(title, locales, plural_forms) 13 | locales = type(locales) == 'table' and locales or {locales} 14 | 15 | describe(title, function() 16 | for _,locale in ipairs(locales) do 17 | for plural_form, numbers in pairs(plural_forms) do 18 | numbers = type(numbers) == 'table' and numbers or {numbers} 19 | it(('%s translates numbers into their correct plural form'):format(locale), function() 20 | for _,n in ipairs(numbers) do 21 | assert.equal(plural.get(locale, n), plural_form) 22 | assert.equal(plural.get(locale, -n), plural_form) 23 | end 24 | end) 25 | end 26 | end 27 | end) 28 | end 29 | 30 | local function words(str) 31 | local result, length = {}, 0 32 | str:gsub("%S+", function(word) 33 | length = length + 1 34 | result[length] = word 35 | end) 36 | return result 37 | end 38 | 39 | it('throws an error with the wrong parameters', function() 40 | assert.error(function() plural.get() end) 41 | assert.error(function() plural.get(1,1) end) 42 | assert.error(function() plural.get('en', 'en') end) 43 | end) 44 | 45 | 46 | test_get('f1', words([[ af en it nb rof teo ]]), { 47 | one = 1, 48 | other = {0, 2, 999, 0.5, 1.2, 2.07} 49 | }) 50 | 51 | test_get('f2', words("ak am bh fil guw hi ln mg nso ti tl wa"), { 52 | one = {0, 1}, 53 | other = {2, 999, 1.2, 2.07} 54 | }) 55 | 56 | test_get('f3', 'ar', { 57 | zero = 0, 58 | one = 1, 59 | two = 2, 60 | few = {3, 10, 103, 110, 203, 210}, 61 | many = {11, 99, 111, 199}, 62 | other = {100, 102, 200, 202, 0.2, 1.07, 3.81} 63 | }) 64 | 65 | test_get('f4', words([[ 66 | az bm bo dz fa hu id ig ii ja jv ka kde kea km kn 67 | ]]), { 68 | other = {0 , 1, 1000, 0.5} 69 | }) 70 | 71 | test_get('f5', words("be bs hr ru sh sr uk"), { 72 | one = {1, 21, 31, 41, 51}, 73 | few = {2,4, 22, 24, 32, 34}, 74 | many = {0, 5, 20, 25, 30, 35, 40}, 75 | other = {1.2, 2.07} 76 | }) 77 | 78 | test_get('f6', 'br', { 79 | one = {1, 21, 31, 41, 51}, 80 | two = {2, 22, 32, 42, 52}, 81 | few = {3, 4, 9, 23, 24, 29}, 82 | many = {1000000, 100000000}, 83 | other = {0, 5, 8, 10, 20, 25, 28, 1.2, 2.07} 84 | }) 85 | 86 | test_get('f7', {'cz','sk'}, { 87 | one = 1, 88 | few = {2, 3, 4}, 89 | other = {0, 5, 8, 10, 1.2, 2.07} 90 | }) 91 | 92 | test_get('f8', 'cy', { 93 | zero = 0, 94 | one = 1, 95 | two = 2, 96 | few = 3, 97 | many = 6, 98 | other = {4, 5, 7, 10, 101, 0.2, 1.07, 3.81} 99 | }) 100 | 101 | test_get('f9', {'ff', 'fr', 'kab'}, { 102 | one = {0, 0.1, 0.5, 1, 1.5, 1.8}, 103 | other = {2, 3, 10, 20, 2.07} 104 | }) 105 | 106 | test_get('f10', 'ga', { 107 | one = 1, 108 | two = 2, 109 | few = {3, 4, 5, 6}, 110 | many = {7, 8, 9, 10}, 111 | other = {0, 11, 12, 20, 25, 100, 1.2, 2.07 } 112 | }) 113 | 114 | test_get('f11', 'gd', { 115 | one = {1, 11}, 116 | two = {2, 12}, 117 | few = {3, 10, 13, 19}, 118 | other = {0, 20, 100, 1.2, 2.07} 119 | }) 120 | 121 | test_get('f12', 'gv', { 122 | one = {0, 1, 2, 11, 12, 20, 21, 22}, 123 | other = {3, 4, 5, 6, 7, 8, 9, 10, 13, 14, 1.5} 124 | }) 125 | 126 | test_get('f13', words('iu kw naq se sma smi smj smn sms'), { 127 | one = 1, 128 | two = 2, 129 | other = {0, 3, 10, 1.2, 2.07} 130 | }) 131 | 132 | test_get('f14', 'ksh', { 133 | zero = 0, 134 | one = 1, 135 | other = {2, 3, 5, 10, 100, 2.3, 1.07} 136 | }) 137 | 138 | test_get('f15', 'lag', { 139 | zero = 0, 140 | one = {0.5, 1, 1.5, 1.97}, 141 | other = {2, 3, 10, 100, 2.10} 142 | }) 143 | 144 | test_get('f16', 'lt', { 145 | one = {1, 21, 31, 41, 51, 61}, 146 | few = {2, 3, 4, 5, 6, 7, 8, 9, 22, 23, 24}, 147 | other = {0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 40, 50, 1.5, 2.07} 148 | }) 149 | 150 | test_get('f17', 'lv', { 151 | zero = 0, 152 | one = {1, 21, 31, 41, 51, 61}, 153 | other = {2, 5, 10, 15, 20, 22, 23, 30, 32, 33, 40, 0.2, 2.07} 154 | }) 155 | 156 | test_get('f18', 'mk', { 157 | one = {1, 21, 31, 41, 51, 61}, 158 | other = {0, 2, 5, 10, 100, 0.2, 2.07} 159 | }) 160 | 161 | test_get('f19', {'mo','ro'}, { 162 | one = 1, 163 | few = {0, 2, 10, 15, 19, 101, 119, 201, 219}, 164 | other = {20, 100, 120, 200, 220, 300, 1.2, 2.07} 165 | }) 166 | 167 | test_get('f20', 'mt', { 168 | one = 1, 169 | few = {0, 2, 5, 10, 102, 105, 110, 202, 205, 210}, 170 | many = {11, 15, 19, 111, 115, 119, 211, 215, 219}, 171 | other = {20, 21, 50, 53, 101, 220, 221, 1.4, 11.61, 20.81} 172 | }) 173 | 174 | test_get('f21', 'pl', { 175 | one = 1, 176 | few = {2, 3, 4, 22, 23, 24, 32, 33, 34}, 177 | many = {0, 5, 6, 7, 8, 9, 10, 15, 20, 21, 25, 26, 27, 28, 29, 30, 31, 35}, 178 | other = {1.2, 2.7, 5.94} 179 | }) 180 | 181 | test_get('f22', 'shi', { 182 | one = {0, 1}, 183 | other = {2, 5, 10, 100, 1.2, 2.7, 5.94} 184 | }) 185 | 186 | test_get('f23', 'sl', { 187 | one = {1, 101, 201, 301, 401}, 188 | two = {2, 102, 202, 302, 402}, 189 | few = {3, 4, 103, 104, 203, 204}, 190 | other = {0, 5, 6, 7, 105, 106, 107, 1.2, 11.5, 3.4} 191 | }) 192 | 193 | test_get('f24', 'tzm', { 194 | one = {0, 1, 11, 12, 15, 20, 25, 50, 98, 99}, 195 | other = {2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 101, 102, 0.5, 1.7} 196 | }) 197 | 198 | describe("When the locale is not found", function() 199 | describe("When a default function is set", function() 200 | before_each(function() 201 | plural.setDefaultFunction(function() return 'nothing' end) 202 | end) 203 | 204 | test_get('non-existing languages use it', {'klingon', 'elvish'}, { 205 | nothing = {0, 1, 1000, 0.5} 206 | }) 207 | 208 | test_get('existing languages do not use it', {'fr'}, { 209 | one = {0, 0.1, 0.5, 1, 1.5, 1.8}, 210 | other = {2, 3, 10, 20, 2.07} 211 | }) 212 | end) 213 | 214 | describe("When a default function is not set", function() 215 | test_get('non-existing languages use english', {'klingon', 'elvish'}, { 216 | one = 1, 217 | other = {0, 2, 1000, 0.5} 218 | }) 219 | end) 220 | end) 221 | end) 222 | end) 223 | -------------------------------------------------------------------------------- /spec/test_interpolate.lua: -------------------------------------------------------------------------------- 1 | local interpolate = require 'smiti18n.interpolate' 2 | 3 | describe('smiti18n.interpolate', function() 4 | it("exists", function() 5 | assert.equal('table', type(interpolate)) 6 | end) 7 | 8 | it("performs standard interpolation via string.format", function() 9 | assert.equal("My name is John, I am 13", interpolate("My name is %s, I am %d", {"John", 13})) 10 | end) 11 | 12 | it("does not try to interpolate strings with percentages on it", function() 13 | assert.equal("Pepe feels 100%!", interpolate("%{name} feels 100%!", {name = "Pepe"})) 14 | end) 15 | 16 | describe("When interpolating with hash values", function() 17 | 18 | it("converts non-existing items in nil values without error", function() 19 | assert.equal("Nil = nil", interpolate("Nil = %{null}")) 20 | end) 21 | 22 | it("converts variables in stringifield values", function() 23 | assert.equal("My name is John, I am 13", 24 | interpolate("My name is %{name}, I am %{age}", {name = "John", age = 13})) 25 | end) 26 | 27 | it("ignores spaces inside the brackets", function() 28 | assert.equal("My name is John, I am 13", 29 | interpolate("My name is %{ name }, I am %{ age }", {name = "John", age = 13})) 30 | end) 31 | 32 | it("is escaped via double %%", function() 33 | assert.equal("I am a %{blue} robot.", 34 | interpolate("I am a %%{blue} robot.")) 35 | end) 36 | 37 | end) 38 | 39 | describe("When interpolating with hash values and formats", function() 40 | it("converts non-existing items in nil values without error", function() 41 | assert.equal("Nil = nil", interpolate("Nil = %.s")) 42 | end) 43 | 44 | it("converts variables in stringifield values", function() 45 | assert.equal("My name is John, I am 13", 46 | interpolate("My name is %.s, I am %.d", {name = "John", age = 13})) 47 | end) 48 | 49 | it("ignores spaces inside the brackets", function() 50 | assert.equal("My name is John, I am 13", 51 | interpolate("My name is %< name >.s, I am %< age >.d", {name = "John", age = 13})) 52 | end) 53 | 54 | it("is escaped via double %%", function() 55 | assert.equal("I am a %.s robot.", interpolate("I am a %%.s robot.")) 56 | end) 57 | end) 58 | 59 | it("Interpolates everything at the same time", function() 60 | assert.equal('A nil ref and %.d and spaced and "quoted" and something', 61 | interpolate("A %{null} ref and %%.d and %{ spaced } and %.q and %s", { 62 | "something", 63 | spaced = "spaced", 64 | quoted = "quoted" 65 | }) 66 | ) 67 | end) 68 | 69 | -- Add new tests here, before the final end) 70 | describe('Multiple format specifiers', function() 71 | it("handles multiple numeric formats in one string", function() 72 | assert.equal( 73 | "Int: 42, Float: 3.14, Exp: 1.23e+06", 74 | interpolate( 75 | "Int: %s, Float: %s, Exp: %s", 76 | {"42", "3.14", "1.23e+06"})) 77 | end) 78 | 79 | it("handles repeated format specifiers", function() 80 | assert.equal( 81 | "Value is 42 and also 42", 82 | interpolate("Value is %s and also %s", {"42", "42"})) 83 | end) 84 | 85 | it("handles escaped format chars correctly", function() 86 | assert.equal( 87 | "Format: %d", 88 | interpolate("Format: %%d") 89 | ) 90 | end) 91 | end) 92 | 93 | describe('Edge cases', function() 94 | it("handles simple variable references", function() 95 | assert.equal( 96 | "Value: test", 97 | interpolate("Value: %{val}", {val = "test"})) 98 | end) 99 | 100 | it("handles invalid format specifiers gracefully", function() 101 | assert.error(function() 102 | interpolate("%d", {"not a number"}) 103 | end) 104 | end) 105 | 106 | it("ignores escaped format specifiers", function() 107 | assert.equal( 108 | "Raw %.d here", 109 | interpolate("Raw %%.d here", {num = 42})) 110 | end) 111 | 112 | it("handles escaped format characters", function() 113 | assert.equal("100%", interpolate("100%%")) 114 | assert.equal("50% complete", interpolate("50%% complete")) 115 | end) 116 | 117 | it("handles format specifiers", function() 118 | assert.equal("Test %s", interpolate("Test %%s")) 119 | assert.equal("Value %d", interpolate("Value %%d")) 120 | end) 121 | end) 122 | 123 | describe('unescapePercentages', function() 124 | it('handles escaped format chars correctly', function() 125 | local result = interpolate("Format: %%d") 126 | assert.equal("Format: %d", result) 127 | end) 128 | 129 | it('handles single values with escapes', function() 130 | local result = interpolate("Number: %%d %d", {42}) 131 | assert.equal("Number: %d 42", result) 132 | end) 133 | 134 | it('handles multiple escapes', function() 135 | -- Test double %% (escapes to single %) 136 | local result = interpolate("Test: %%d%%d", {}) 137 | assert.equal("Test: %d%d", result) 138 | 139 | -- Test triple %%% with value 140 | result = interpolate("Value: %%%d", {123}) 141 | assert.equal("Value: %123", result) 142 | end) 143 | 144 | it('handles special format characters differently', function() 145 | -- Test format character that exists in FORMAT_CHARS table (like s,d,f) 146 | local result = interpolate("Test: %%s %%d %%f", {}) 147 | assert.equal("Test: %s %d %f", result) 148 | 149 | -- Test non-format character (z is not in FORMAT_CHARS) 150 | result = interpolate("Test: %%z", {}) 151 | assert.equal("Test: %z", result) -- Updated expectation - all %% are converted to % 152 | end) 153 | 154 | it('exercises all format character paths', function() 155 | -- Test format character (d) with proper value 156 | local result = interpolate("Test: %%%d %%d", {42}) 157 | assert.equal("Test: %42 %d", result) 158 | 159 | -- Test non-format character with escaped % 160 | result = interpolate("Test: %%k", {}) 161 | assert.equal("Test: %k", result) 162 | 163 | -- Mix both in single test to ensure branches are hit 164 | result = interpolate("Mix: %%%d %%x", {99}) 165 | assert.equal("Mix: %99 %x", result) 166 | end) 167 | end) 168 | 169 | describe('getInterpolationKey', function() 170 | it("finds first valid interpolation key", function() 171 | assert.equal( 172 | "name", 173 | interpolate.getInterpolationKey("Text %{name}", {name = "test"})) 174 | end) 175 | 176 | it("returns nil when no valid keys found", function() 177 | assert.is_nil( 178 | interpolate.getInterpolationKey("No vars here") 179 | ) 180 | end) 181 | 182 | it("handles format specifiers", function() 183 | assert.equal( 184 | "num", 185 | interpolate.getInterpolationKey("Format %.d here", {num = 42})) 186 | end) 187 | end) 188 | end) 189 | -------------------------------------------------------------------------------- /smiti18n/format.lua: -------------------------------------------------------------------------------- 1 | local format = {} 2 | 3 | local DEFAULT_NAMES = { 4 | short_month_names = { 5 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", 6 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 7 | }, 8 | long_month_names = { 9 | "January", "February", "March", "April", "May", "June", 10 | "July", "August", "September", "October", "November", "December" 11 | }, 12 | short_day_names = { 13 | "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 14 | }, 15 | long_day_names = { 16 | "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", 17 | "Friday", "Saturday" 18 | } 19 | } 20 | 21 | -- Private variables 22 | local config = {} 23 | local default_config = { 24 | currency = { 25 | symbol = "XXX", 26 | name = "Currency", 27 | short_name = "XXX", 28 | decimal_symbol = ".", -- ISO standard decimal point 29 | thousand_separator = " ", -- ISO standard space 30 | fract_digits = 2, 31 | positive_symbol = "", 32 | negative_symbol = "-", 33 | positive_format = "%c %p%q", 34 | negative_format = "%c %p%q" 35 | }, 36 | number = { 37 | decimal_symbol = ".", -- ISO standard decimal point 38 | thousand_separator = " ", -- ISO standard space 39 | fract_digits = 2, 40 | positive_symbol = "", 41 | negative_symbol = "-" 42 | }, 43 | date_time = { 44 | long_time = "%H:%M:%S", 45 | short_time = "%H:%M", 46 | long_date = "%B %d, %Y", 47 | short_date = "%m/%d/%Y", 48 | long_date_time = "%B %d, %Y %H:%M:%S", 49 | short_date_time = "%m/%d/%Y %H:%M" 50 | }, 51 | short_month_names = DEFAULT_NAMES.short_month_names, 52 | long_month_names = DEFAULT_NAMES.long_month_names, 53 | short_day_names = DEFAULT_NAMES.short_day_names, 54 | long_day_names = DEFAULT_NAMES.long_day_names 55 | } 56 | 57 | -- Helper functions 58 | local function separateThousand(amount, separator) 59 | local formatted = amount 60 | while true do 61 | local k 62 | formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1' .. separator .. '%2') 63 | if k == 0 then break end 64 | end 65 | return formatted 66 | end 67 | 68 | local function round(val, decimal) 69 | return math.floor((val * 10 ^ decimal) + 0.5) / (10 ^ decimal) 70 | end 71 | 72 | local function formatNum(amount, digits, separator, decimal) 73 | digits = tonumber(digits) or 0 -- Ensure digits is a number 74 | local famount = math.floor(math.abs(round(amount, digits))) 75 | local remain = round(math.abs(amount) - famount, digits) 76 | local formatted = separateThousand(famount, separator) 77 | 78 | if digits > 0 then 79 | remain = string.sub(tostring(remain), 3) 80 | formatted = formatted .. decimal .. remain .. string.rep("0", digits - #remain) 81 | end 82 | 83 | return formatted 84 | end 85 | 86 | -- Configuration functions 87 | function format.configure(formats) 88 | -- Always start with default config 89 | config = {} 90 | -- Since we know all default_config entries are tables 91 | for k,v in pairs(default_config) do 92 | config[k] = {} 93 | for k2,v2 in pairs(v) do 94 | config[k][k2] = v2 95 | end 96 | end 97 | 98 | -- Override with provided formats 99 | if formats then 100 | for k,v in pairs(formats) do 101 | if type(v) == 'table' then 102 | config[k] = config[k] or {} 103 | for k2,v2 in pairs(v) do 104 | config[k][k2] = v2 105 | end 106 | end 107 | end 108 | end 109 | end 110 | 111 | function format.get_config() 112 | return config 113 | end 114 | 115 | -- Main formatting functions 116 | local function getConfigSection(section, cfg) 117 | return cfg or (config[section] or default_config[section]) 118 | end 119 | 120 | function format.number(number, cfg) 121 | local config_section = getConfigSection('number', cfg) 122 | local digits = config_section.fract_digits 123 | if digits == nil then digits = 2 end -- Default to 2 for ISO standard 124 | local separator = config_section.thousand_separator or " " 125 | local decimal = config_section.decimal_symbol or "." 126 | local polarity = number < 0 and (config_section.negative_symbol or "-") or (config_section.positive_symbol or "") 127 | 128 | return polarity .. formatNum(math.abs(number), digits, separator, decimal) 129 | end 130 | 131 | function format.price(amount, cfg) 132 | local cfg_section = getConfigSection('currency', cfg) 133 | local digits = cfg_section.fract_digits or 2 134 | local separator = cfg_section.thousand_separator or " " 135 | local decimal = cfg_section.decimal_symbol or "." 136 | local symbol = cfg_section.symbol or "XXX" 137 | local polarity = amount < 0 and 138 | (cfg_section.negative_symbol or "-") or (cfg_section.positive_symbol or "") 139 | local pattern = amount < 0 and 140 | (cfg_section.negative_format or "%c %p%q") or (cfg_section.positive_format or "%c %p%q") 141 | 142 | -- Validate pattern has required components 143 | if not pattern:match("%%c") or not pattern:match("%%q") then 144 | -- If pattern is invalid, fall back to default pattern 145 | pattern = amount < 0 and default_config.currency.negative_format or default_config.currency.positive_format 146 | end 147 | 148 | -- Format the number first 149 | local formatted_number = formatNum(math.abs(amount), digits, separator, decimal) 150 | 151 | -- Apply the pattern substitutions in correct order 152 | return pattern:gsub("%%p", polarity) 153 | :gsub("%%q", formatted_number) 154 | :gsub("%%c", symbol) 155 | end 156 | 157 | local function getNameArray(arrayType) 158 | -- Either use configured values or fall back to English defaults 159 | -- No explicit nil handling - simple fallback 160 | return config[arrayType] or DEFAULT_NAMES[arrayType] 161 | end 162 | 163 | function format.dateTime(pattern, date, cfg) 164 | local date_time = date or os.date("*t") 165 | local config_section = getConfigSection('date_time', cfg) 166 | 167 | -- Get pattern from config or use default ISO format 168 | if not pattern then 169 | pattern = "%Y-%m-%dT%H:%M:%S" -- ISO 8601 170 | elseif config_section[pattern] then 171 | pattern = config_section[pattern] 172 | end 173 | 174 | -- Guard against nil values in date_time 175 | local hour = tonumber(date_time.hour) or 0 176 | local min = tonumber(date_time.min) or 0 177 | local sec = tonumber(date_time.sec) or 0 178 | local day = tonumber(date_time.day) or 1 179 | local month = tonumber(date_time.month) or 1 180 | local year = tonumber(date_time.year) or 1970 181 | local wday = tonumber(date_time.wday) or 1 182 | 183 | -- Get name arrays with fallbacks 184 | local long_days = getNameArray('long_day_names') 185 | local long_months = getNameArray('long_month_names') 186 | local short_days = getNameArray('short_day_names') 187 | local short_months = getNameArray('short_month_names') 188 | 189 | -- Format with custom substitutions (remove redundant result variable) 190 | return pattern:gsub("%%H", string.format("%02d", hour)) 191 | :gsub("%%M", string.format("%02d", min)) 192 | :gsub("%%i", string.format("%02d", min)) 193 | :gsub("%%S", string.format("%02d", sec)) 194 | :gsub("%%s", string.format("%02d", sec)) 195 | :gsub("%%d", string.format("%02d", day)) 196 | :gsub("%%m", string.format("%02d", month)) 197 | :gsub("%%Y", tostring(year)) 198 | :gsub("%%l", long_days[wday] or DEFAULT_NAMES.long_day_names[wday] or "") 199 | :gsub("%%F", long_months[month] or DEFAULT_NAMES.long_month_names[month] or "") 200 | :gsub("%%a", short_days[wday] or DEFAULT_NAMES.short_day_names[wday] or "") 201 | :gsub("%%b", short_months[month] or DEFAULT_NAMES.short_month_names[month] or "") 202 | end 203 | 204 | return format 205 | -------------------------------------------------------------------------------- /smiti18n/plural.lua: -------------------------------------------------------------------------------- 1 | local plural = {} 2 | local defaultFunction = nil 3 | -- helper functions 4 | 5 | local function assertPresentString(functionName, paramName, value) 6 | if type(value) ~= 'string' or #value == 0 then 7 | local msg = "Expected param %s of function %s to be a string, but got %s (a value of type %s) instead" 8 | error(msg:format(paramName, functionName, tostring(value), type(value))) 9 | end 10 | end 11 | 12 | local function assertNumber(functionName, paramName, value) 13 | if type(value) ~= 'number' then 14 | local msg = "Expected param %s of function %s to be a number, but got %s (a value of type %s) instead" 15 | error(msg:format(paramName, functionName, tostring(value), type(value))) 16 | end 17 | end 18 | 19 | -- transforms "foo bar baz" into {'foo','bar','baz'} 20 | local function words(str) 21 | local result, length = {}, 0 22 | str:gsub("%S+", function(word) 23 | length = length + 1 24 | result[length] = word 25 | end) 26 | return result 27 | end 28 | 29 | local function isInteger(n) 30 | return n == math.floor(n) 31 | end 32 | 33 | local function between(value, min, max) 34 | return value >= min and value <= max 35 | end 36 | 37 | local function inside(v, list) 38 | for i=1, #list do 39 | if v == list[i] then return true end 40 | end 41 | return false 42 | end 43 | 44 | 45 | -- pluralization functions 46 | 47 | local pluralization = {} 48 | 49 | local f1 = function(n) 50 | return n == 1 and "one" or "other" 51 | end 52 | pluralization[f1] = words([[ 53 | af asa bem bez bg bn brx ca cgg chr da de dv ee el 54 | en eo es et eu fi fo fur fy gl gsw gu ha haw he is 55 | it jmc kaj kcg kk kl ksb ku lb lg mas ml mn mr nah 56 | nb nd ne nl nn no nr ny nyn om or pa pap ps pt rm 57 | rof rwk saq seh sn so sq ss ssy st sv sw syr ta te 58 | teo tig tk tn ts ur ve vun wae xh xog zu 59 | ]]) 60 | 61 | local f2 = function(n) 62 | return (n == 0 or n == 1) and "one" or "other" 63 | end 64 | pluralization[f2] = words("ak am bh fil guw hi ln mg nso ti tl wa") 65 | 66 | local f3 = function(n) 67 | if not isInteger(n) then return 'other' end 68 | return (n == 0 and "zero") or 69 | (n == 1 and "one") or 70 | (n == 2 and "two") or 71 | (between(n % 100, 3, 10) and "few") or 72 | (between(n % 100, 11, 99) and "many") or 73 | "other" 74 | end 75 | pluralization[f3] = {'ar'} 76 | 77 | local f4 = function() 78 | return "other" 79 | end 80 | pluralization[f4] = words([[ 81 | az bm bo dz fa hu id ig ii ja jv ka kde kea km kn 82 | ko lo ms my root sah ses sg th to tr vi wo yo zh 83 | ]]) 84 | 85 | local f5 = function(n) 86 | if not isInteger(n) then return 'other' end 87 | local n_10, n_100 = n % 10, n % 100 88 | return (n_10 == 1 and n_100 ~= 11 and 'one') or 89 | (between(n_10, 2, 4) and not between(n_100, 12, 14) and 'few') or 90 | ((n_10 == 0 or between(n_10, 5, 9) or between(n_100, 11, 14)) and 'many') or 91 | 'other' 92 | end 93 | pluralization[f5] = words('be bs hr ru sh sr uk') 94 | 95 | local f6 = function(n) 96 | if not isInteger(n) then return 'other' end 97 | local n_10, n_100 = n % 10, n % 100 98 | return (n_10 == 1 and not inside(n_100, {11,71,91}) and 'one') or 99 | (n_10 == 2 and not inside(n_100, {12,72,92}) and 'two') or 100 | (inside(n_10, {3,4,9}) and 101 | not between(n_100, 10, 19) and 102 | not between(n_100, 70, 79) and 103 | not between(n_100, 90, 99) 104 | and 'few') or 105 | (n ~= 0 and n % 1000000 == 0 and 'many') or 106 | 'other' 107 | end 108 | pluralization[f6] = {'br'} 109 | 110 | local f7 = function(n) 111 | return (n == 1 and 'one') or 112 | ((n == 2 or n == 3 or n == 4) and 'few') or 113 | 'other' 114 | end 115 | pluralization[f7] = {'cz', 'sk'} 116 | 117 | local f8 = function(n) 118 | return (n == 0 and 'zero') or 119 | (n == 1 and 'one') or 120 | (n == 2 and 'two') or 121 | (n == 3 and 'few') or 122 | (n == 6 and 'many') or 123 | 'other' 124 | end 125 | pluralization[f8] = {'cy'} 126 | 127 | local f9 = function(n) 128 | return (n >= 0 and n < 2 and 'one') or 129 | 'other' 130 | end 131 | pluralization[f9] = {'ff', 'fr', 'kab'} 132 | 133 | local f10 = function(n) 134 | return (n == 1 and 'one') or 135 | (n == 2 and 'two') or 136 | ((n == 3 or n == 4 or n == 5 or n == 6) and 'few') or 137 | ((n == 7 or n == 8 or n == 9 or n == 10) and 'many') or 138 | 'other' 139 | end 140 | pluralization[f10] = {'ga'} 141 | 142 | local f11 = function(n) 143 | return ((n == 1 or n == 11) and 'one') or 144 | ((n == 2 or n == 12) and 'two') or 145 | (isInteger(n) and (between(n, 3, 10) or between(n, 13, 19)) and 'few') or 146 | 'other' 147 | end 148 | pluralization[f11] = {'gd'} 149 | 150 | local f12 = function(n) 151 | local n_10 = n % 10 152 | return ((n_10 == 1 or n_10 == 2 or n % 20 == 0) and 'one') or 153 | 'other' 154 | end 155 | pluralization[f12] = {'gv'} 156 | 157 | local f13 = function(n) 158 | return (n == 1 and 'one') or 159 | (n == 2 and 'two') or 160 | 'other' 161 | end 162 | pluralization[f13] = words('iu kw naq se sma smi smj smn sms') 163 | 164 | local f14 = function(n) 165 | return (n == 0 and 'zero') or 166 | (n == 1 and 'one') or 167 | 'other' 168 | end 169 | pluralization[f14] = {'ksh'} 170 | 171 | local f15 = function(n) 172 | return (n == 0 and 'zero') or 173 | (n > 0 and n < 2 and 'one') or 174 | 'other' 175 | end 176 | pluralization[f15] = {'lag'} 177 | 178 | local f16 = function(n) 179 | if not isInteger(n) then return 'other' end 180 | if between(n % 100, 11, 19) then return 'other' end 181 | local n_10 = n % 10 182 | return (n_10 == 1 and 'one') or 183 | (between(n_10, 2, 9) and 'few') or 184 | 'other' 185 | end 186 | pluralization[f16] = {'lt'} 187 | 188 | local f17 = function(n) 189 | return (n == 0 and 'zero') or 190 | ((n % 10 == 1 and n % 100 ~= 11) and 'one') or 191 | 'other' 192 | end 193 | pluralization[f17] = {'lv'} 194 | 195 | local f18 = function(n) 196 | return((n % 10 == 1 and n ~= 11) and 'one') or 197 | 'other' 198 | end 199 | pluralization[f18] = {'mk'} 200 | 201 | local f19 = function(n) 202 | return (n == 1 and 'one') or 203 | ((n == 0 or 204 | (n ~= 1 and isInteger(n) and between(n % 100, 1, 19))) 205 | and 'few') or 206 | 'other' 207 | end 208 | pluralization[f19] = {'mo', 'ro'} 209 | 210 | local f20 = function(n) 211 | if n == 1 then return 'one' end 212 | if not isInteger(n) then return 'other' end 213 | local n_100 = n % 100 214 | return ((n == 0 or between(n_100, 2, 10)) and 'few') or 215 | (between(n_100, 11, 19) and 'many') or 216 | 'other' 217 | end 218 | pluralization[f20] = {'mt'} 219 | 220 | local f21 = function(n) 221 | if n == 1 then return 'one' end 222 | if not isInteger(n) then return 'other' end 223 | local n_10, n_100 = n % 10, n % 100 224 | 225 | return ((between(n_10, 2, 4) and not between(n_100, 12, 14)) and 'few') or 226 | ((n_10 == 0 or n_10 == 1 or between(n_10, 5, 9) or between(n_100, 12, 14)) and 'many') or 227 | 'other' 228 | end 229 | pluralization[f21] = {'pl'} 230 | 231 | local f22 = function(n) 232 | return (n == 0 or n == 1) and 'one' or 233 | 'other' 234 | end 235 | pluralization[f22] = {'shi'} 236 | 237 | local f23 = function(n) 238 | local n_100 = n % 100 239 | return (n_100 == 1 and 'one') or 240 | (n_100 == 2 and 'two') or 241 | ((n_100 == 3 or n_100 == 4) and 'few') or 242 | 'other' 243 | end 244 | pluralization[f23] = {'sl'} 245 | 246 | local f24 = function(n) 247 | return (isInteger(n) and (n == 0 or n == 1 or between(n, 11, 99)) and 'one') 248 | or 'other' 249 | end 250 | pluralization[f24] = {'tzm'} 251 | 252 | local pluralizationFunctions = {} 253 | for f,locales in pairs(pluralization) do 254 | for _,locale in ipairs(locales) do 255 | pluralizationFunctions[locale] = f 256 | end 257 | end 258 | 259 | -- public interface 260 | 261 | function plural.get(locale, n) 262 | assertPresentString('i18n.plural.get', 'locale', locale) 263 | assertNumber('i18n.plural.get', 'n', n) 264 | 265 | local f = pluralizationFunctions[locale] or defaultFunction 266 | 267 | return f(math.abs(n)) 268 | end 269 | 270 | function plural.setDefaultFunction(f) 271 | defaultFunction = f 272 | end 273 | 274 | function plural.reset() 275 | defaultFunction = pluralizationFunctions['en'] 276 | end 277 | 278 | plural.reset() 279 | 280 | return plural 281 | -------------------------------------------------------------------------------- /smiti18n/init.lua: -------------------------------------------------------------------------------- 1 | -- luacheck: globals love 2 | local unpack = unpack or table.unpack -- lua 5.2 compat 3 | local i18n = {} 4 | 5 | local store = {} -- translations 6 | local formatConfigs = {} -- format configurations 7 | local locale 8 | local customPluralizeFunction 9 | local defaultLocale = 'en' 10 | local fallbackLocale = defaultLocale 11 | 12 | local currentFilePath = (...):gsub("%.init$","") 13 | 14 | local format = require(currentFilePath .. '.format') 15 | local plural = require(currentFilePath .. '.plural') 16 | local interpolate = require(currentFilePath .. '.interpolate') 17 | local variants = require(currentFilePath .. '.variants') 18 | local version = require(currentFilePath .. '.version') 19 | 20 | i18n.format = format 21 | i18n.plural = plural 22 | i18n.interpolate = interpolate 23 | i18n.variants = variants 24 | i18n.version = version 25 | i18n._VERSION = version 26 | 27 | -- private stuff 28 | 29 | -- Pre-compile frequently used patterns 30 | local DOTPLIT_PATTERN = "[^%.]+" 31 | local function dotSplit(str) 32 | local fields, length = {}, 0 33 | for part in str:gmatch(DOTPLIT_PATTERN) do 34 | length = length + 1 35 | fields[length] = part 36 | end 37 | return fields, length 38 | end 39 | 40 | local function hasLove() 41 | local success, loveEngine = pcall(function() return love end) 42 | return success and type(loveEngine) == 'table' and type(loveEngine.filesystem) == 'table' 43 | end 44 | 45 | local function isPluralTable(t) 46 | return type(t) == 'table' and type(t.other) == 'string' 47 | end 48 | 49 | local function isPresent(str) 50 | return type(str) == 'string' and #str > 0 51 | end 52 | 53 | local function isArray(t) 54 | return type(t) == 'table' and (#t > 0 or next(t) == nil) 55 | end 56 | 57 | local function assertPresent(functionName, paramName, value) 58 | if isPresent(value) then return end 59 | 60 | local msg = "i18n.%s requires a non-empty string on its %s. Got %s (a %s value)." 61 | error(msg:format(functionName, paramName, tostring(value), type(value))) 62 | end 63 | 64 | local function assertPresentOrPlural(functionName, paramName, value) 65 | if isPresent(value) or isPluralTable(value) or isArray(value) then return end 66 | 67 | local msg = "i18n.%s requires a non-empty string or plural-form table on its %s. Got %s (a %s value)." 68 | error(msg:format(functionName, paramName, tostring(value), type(value))) 69 | end 70 | 71 | local function assertPresentOrTable(functionName, paramName, value) 72 | if isPresent(value) or type(value) == 'table' then return end 73 | 74 | local msg = "i18n.%s requires a non-empty string or table on its %s. Got %s (a %s value)." 75 | error(msg:format(functionName, paramName, tostring(value), type(value))) 76 | end 77 | 78 | local function assertFunctionOrNil(functionName, paramName, value) 79 | if value == nil or type(value) == 'function' then return end 80 | 81 | local msg = "i18n.%s requires a function (or nil) on param %s. Got %s (a %s value)." 82 | error(msg:format(functionName, paramName, tostring(value), type(value))) 83 | end 84 | 85 | local function defaultPluralizeFunction(loc, count) 86 | return plural.get(variants.root(loc), count) 87 | end 88 | 89 | local function pluralize(t, loc, data) 90 | assertPresentOrPlural('interpolatePluralTable', 't', t) 91 | data = data or {} 92 | local key 93 | for _, v in pairs(t) do 94 | key = interpolate.getInterpolationKey(v, data) 95 | if key then 96 | break 97 | end 98 | end 99 | local count = data[key or "count"] or 1 100 | local plural_form 101 | if customPluralizeFunction then 102 | plural_form = customPluralizeFunction(count) 103 | else 104 | plural_form = defaultPluralizeFunction(loc, count) 105 | end 106 | return t[plural_form] 107 | end 108 | 109 | local function treatNode(node, loc, data) 110 | if isArray(node) then 111 | local iter = {ipairs(node)} 112 | node = {} 113 | for k,v in unpack(iter) do 114 | node[k] = treatNode(v, loc, data) 115 | end 116 | elseif type(node) == 'string' then 117 | return interpolate(node, data) 118 | elseif isPluralTable(node) then 119 | -- Make sure that count has a default of 1 120 | local newdata = data 121 | if data.count == nil then 122 | newdata = {count = 1} -- Simplified - no need to copy other values 123 | end 124 | return interpolate(pluralize(node, loc, newdata), newdata) 125 | end 126 | return node 127 | end 128 | 129 | local function recursiveLoad(currentContext, data) 130 | -- Extract _formats before processing translations 131 | if data._formats then 132 | if currentContext then 133 | formatConfigs[currentContext] = data._formats 134 | format.configure(data._formats) -- Configure format module immediately 135 | end 136 | data._formats = nil 137 | end 138 | 139 | -- Process translations 140 | local composedKey 141 | for k,v in pairs(data) do 142 | composedKey = (currentContext and (currentContext .. '.') or "") .. tostring(k) 143 | assertPresent('load', composedKey, k) 144 | assertPresentOrTable('load', composedKey, v) 145 | if type(v) == 'string' or isArray(v) then 146 | i18n.set(composedKey, v) 147 | else 148 | recursiveLoad(composedKey, v) 149 | end 150 | end 151 | end 152 | 153 | local function localizedTranslate(key, loc, data) 154 | local path, length = dotSplit(loc .. "." .. key) 155 | local node = store 156 | 157 | for i=1, length do 158 | node = node[path[i]] 159 | if not node then return nil end 160 | end 161 | 162 | return treatNode(node, loc, data) 163 | end 164 | 165 | local function appendLocales(primaryLocales, fallbackLocales) 166 | local primaryLen = #primaryLocales 167 | local fallbackLen = #fallbackLocales 168 | -- If both tables are empty, return am empty table 169 | if primaryLen == 0 and fallbackLen == 0 then 170 | return {} 171 | end 172 | 173 | -- If primary is empty, return fallback 174 | if primaryLen == 0 then 175 | return fallbackLocales 176 | end 177 | 178 | -- If fallback is empty, return primary 179 | if fallbackLen == 0 then 180 | return primaryLocales 181 | end 182 | 183 | local result = {} 184 | 185 | for i = 1, primaryLen do 186 | result[i] = primaryLocales[i] 187 | end 188 | 189 | for i = 1, fallbackLen do 190 | result[primaryLen + i] = fallbackLocales[i] 191 | end 192 | 193 | return result 194 | end 195 | 196 | -- public interface 197 | 198 | function i18n.set(key, value) 199 | assertPresent('set', 'key', key) 200 | assertPresentOrPlural('set', 'value', value) 201 | 202 | local path, length = dotSplit(key) 203 | local node = store 204 | 205 | for i=1, length-1 do 206 | key = path[i] 207 | node[key] = node[key] or {} 208 | node = node[key] 209 | end 210 | 211 | local lastKey = path[length] 212 | node[lastKey] = value 213 | end 214 | 215 | function i18n.translate(key, data) 216 | assertPresent('translate', 'key', key) 217 | 218 | data = data or {} 219 | local usedLocales 220 | local locales = locale 221 | if type(locale) == 'string' then 222 | locales = {locale} 223 | end 224 | if isPresent(data.locale) then 225 | usedLocales = appendLocales({data.locale}, locales) 226 | else 227 | usedLocales = appendLocales({}, locales) 228 | end 229 | 230 | table.insert(usedLocales, fallbackLocale) 231 | local fallbacks = variants.fallbacks(usedLocales) 232 | for i=1, #fallbacks do 233 | local value = localizedTranslate(key, fallbacks[i], data) 234 | if value then return value end 235 | end 236 | 237 | if data.default then 238 | return interpolate(data.default, data) 239 | end 240 | end 241 | 242 | function i18n.setLocale(newLocale, newPluralizeFunction) 243 | assertPresentOrTable('setLocale', 'newLocale', newLocale) 244 | assertFunctionOrNil('setLocale', 'newPluralizeFunction', newPluralizeFunction) 245 | locale = newLocale 246 | customPluralizeFunction = newPluralizeFunction 247 | 248 | -- Only use format config if it exists for exact locale 249 | local loc = type(newLocale) == 'table' and newLocale[1] or newLocale 250 | format.configure(formatConfigs[loc]) -- Will use ISO defaults if nil 251 | end 252 | 253 | function i18n.setFallbackLocale(newFallbackLocale) 254 | assertPresent('setFallbackLocale', 'newFallbackLocale', newFallbackLocale) 255 | fallbackLocale = newFallbackLocale 256 | end 257 | 258 | function i18n.getFallbackLocale() 259 | return fallbackLocale 260 | end 261 | 262 | function i18n.getLocale() 263 | return locale 264 | end 265 | 266 | function i18n.load(data) 267 | recursiveLoad(nil, data) 268 | end 269 | 270 | function i18n.loadFile(path) 271 | local data 272 | if hasLove() then 273 | -- LÖVE filesystem handling 274 | local loveEngine = love -- store reference to avoid luacheck warning 275 | local contents, readErr = loveEngine.filesystem.read(path) 276 | if not contents then 277 | error("Could not load i18n file: " .. tostring(readErr)) 278 | end 279 | -- Load string as Lua code - use loadstring for 5.1, load for 5.2+ 280 | local chunk, parseErr = (loadstring or load)(contents, path) 281 | if not chunk then 282 | error("Could not parse i18n file: " .. tostring(parseErr)) 283 | end 284 | data = chunk() 285 | else 286 | -- Standard Lua file handling 287 | local chunk, err = loadfile(path) 288 | if not chunk then 289 | error("Could not load i18n file: " .. tostring(err)) 290 | end 291 | data = chunk() 292 | end 293 | 294 | if type(data) ~= 'table' then 295 | error("i18n file must return a table") 296 | end 297 | 298 | i18n.load(data) 299 | end 300 | 301 | -- format configuration setters 302 | local function getFormatConfig() 303 | local loc = locale 304 | if type(loc) == 'table' then 305 | loc = loc[1] 306 | end 307 | 308 | -- Only return exact match, no fallback to other locales 309 | return formatConfigs[loc] 310 | end 311 | 312 | setmetatable(i18n, {__call = function(_, ...) return i18n.translate(...) end}) 313 | 314 | function i18n.reset() 315 | store = {} 316 | formatConfigs = {} 317 | plural.reset() 318 | format.configure(nil) -- Reset to defaults 319 | i18n.setLocale(defaultLocale) 320 | i18n.setFallbackLocale(defaultLocale) 321 | end 322 | 323 | -- Format function delegations 324 | function i18n.formatNumber(number) 325 | local cfg = getFormatConfig() or {} 326 | return format.number(number, cfg.number) 327 | end 328 | 329 | function i18n.formatPrice(amount) 330 | local cfg = getFormatConfig() or {} 331 | return format.price(amount, cfg.currency) 332 | end 333 | 334 | function i18n.formatDate(pattern, date) 335 | local cfg = getFormatConfig() or {} 336 | return format.dateTime(pattern, date, cfg.date_time) 337 | end 338 | 339 | function i18n.configure(formats) 340 | format.configure(formats) 341 | end 342 | 343 | function i18n.getConfig() 344 | return format.get_config() 345 | end 346 | 347 | return i18n 348 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # smiti18n 2 | 3 | A very complete internationalization library for Lua with LÖVE support 🌕💕 4 | 5 | [![Test 🧪](https://github.com/Oval-Tutu/smiti18n/actions/workflows/ci.yml/badge.svg)](https://github.com/Oval-Tutu/smiti18n/actions/workflows/ci.yml) [![Lua Versions](https://img.shields.io/badge/Lua-5.1%20%7C%205.2%20%7C%205.3%20%7C%205.4%20%7C%20JIT-24a6db)](https://github.com/Oval-Tutu/smiti18n) [![LÖVE Versions](https://img.shields.io/badge/L%C3%96VE-11.x-e14895)](https://love2d.org) [![LuaRocks](https://img.shields.io/luarocks/v/flexiondotorg/smiti18n?color=2b3c64)](https://luarocks.org/modules/flexiondotorg/smiti18n) [![License](https://img.shields.io/github/license/Oval-Tutu/smiti18n?color=a01830)](https://github.com/Oval-Tutu/smiti18n/blob/master/LICENSE) 6 | 7 | 8 | ## Introduction 9 | 10 | smiti18n (*pronounced smitten*) is a powerful internationalization (i18n) library that helps you create multilingual applications in Lua and [LÖVE](https://love2d.org/). 11 | 12 | **Core Features:** 🚀 13 | - 📁 Smart file-based loading & fallbacks 14 | - 🔠 Rich text interpolation & pluralization 15 | - 🌏 Locale-aware formatting for numbers, dates and currency 16 | - 💕 Built for LÖVE game engine 17 | 18 | **Rich Game Content:** 🎮 19 | - 💬 Complex dialogue support: 20 | - Branching conversations 21 | - Character-specific translations 22 | - Context-aware responses 23 | - 🎯 53 locales, 650+ game-specific phrases 24 | - 📊 36 regional number formats 25 | 26 | An intuitive API for managing translations forked from [i18n.lua](https://github.com/kikito/i18n.lua) by Enrique García Cota incorporating a [collection of community contributions](https://github.com/kikito/i18n.lua/pulls). 27 | The number, date and time formatting has been ported from [Babel](https://github.com/LuaDist-testing/babel). Includes translations from [PolyglotGamedev](https://github.com/PolyglotGamedev). Significantly expanded test coverage and documentation. 28 | 29 | ### Requirements 30 | 31 | - Lua 5.1-5.4 or LuaJIT 2.0-2.1 32 | - LÖVE 11.0+ (*optional*) 33 | 34 | ### Quick example 35 | 36 | Here's a quick example: 37 | 38 | ```lua 39 | i18n = require 'smiti18n' 40 | 41 | -- Load some translations 42 | i18n.load({ 43 | en = { 44 | greeting = "Hello %{name}!", 45 | messages = { 46 | one = "You have one new message", 47 | other = "You have %{count} new messages" 48 | } 49 | }, 50 | es = { 51 | greeting = "¡Hola %{name}!", 52 | messages = { 53 | one = "Tienes un mensaje nuevo", 54 | other = "Tienes %{count} mensajes nuevos" 55 | } 56 | } 57 | }) 58 | 59 | -- Set the current locale 60 | i18n.setLocale('es') 61 | 62 | -- Use translations 63 | print(i18n('greeting', {name = "Luna"})) -- ¡Hola Luna! 64 | print(i18n('messages', {count = 3})) -- Tienes 3 mensajes nuevos 65 | ``` 66 | 67 | ## Installation 68 | 69 | ### Using LuaRocks 70 | 71 | [smiti18n is available on LuaRocks](https://luarocks.org/modules/flexiondotorg/smiti18n). You can install it with the following command: 72 | 73 | ```shell 74 | luarocks install smiti18n 75 | ``` 76 | 77 | ### Manual Installation 78 | 79 | #### Option 1: Git Clone 80 | 81 | Clone this repository and copy the `smiti18n` folder into your project as something like `lib/smiti18n`. 82 | 83 | ```shell 84 | git clone https://github.com/Oval-Tutu/smiti18n.git 85 | cd smiti18n 86 | cp -r smiti18n your-project/lib/ 87 | ``` 88 | 89 | #### Option 2: Download Release 90 | 91 | 1. Download latest release from [Releases](https://github.com/Oval-Tutu/smiti18n/releases) 92 | 2. Extract the archive 93 | 3. Copy `smiti18n` directory to your project 94 | 95 | Project structure after installation: 96 | 97 | ``` 98 | your-project/ 99 | ├── lib/ 100 | │ └── smiti18n/ 101 | │ ├── init.lua 102 | │ ├── interpolate.lua 103 | │ ├── plural.lua 104 | │ ├── variants.lua 105 | │ └── version.lua 106 | ├── locales/ 107 | │ ├── en-UK.lua 108 | │ └── other-locale-files.lua 109 | └── main.lua 110 | ``` 111 | 112 | #### Using the Library 113 | 114 | ```lua 115 | -- Require smiti18n in your code 116 | local i18n = require 'lib.smiti18n' 117 | i18n.loadFile('locales/en-UK.lua') 118 | i18n.setLocale('en-UK') 119 | ``` 120 | 121 | ### Translation Files 122 | 123 | smiti18n supports both single-file and multi-file approaches for managing translations. 124 | 125 | #### Single File 126 | 127 | Store all translations in one file (e.g., `translations.lua`): 128 | 129 | ```lua 130 | -- translations.lua 131 | return { 132 | en = { 133 | greeting = "Hello!", 134 | messages = { 135 | one = "You have one message", 136 | other = "You have %{count} messages" 137 | } 138 | }, 139 | es = { 140 | greeting = "¡Hola!", 141 | messages = { 142 | one = "Tienes un mensaje", 143 | other = "Tienes %{count} mensajes" 144 | } 145 | } 146 | } 147 | 148 | -- Load translations 149 | i18n.loadFile('translations.lua') 150 | ``` 151 | 152 | #### Multiple Files 153 | 154 | Organize translations by language (recommended for larger projects): 155 | 156 | Here's an example project structure: 157 | 158 | ``` 159 | locales/ 160 | ├── en.lua -- English translations 161 | ├── es.lua -- Spanish translations 162 | └── fr.lua -- French translations 163 | ``` 164 | 165 | **`en.lua`** 166 | ```lua 167 | return { 168 | en = { -- Locale key required 169 | greeting = "Hello!", 170 | messages = { 171 | one = "You have one message", 172 | other = "You have %{count} messages" 173 | } 174 | } 175 | } 176 | ``` 177 | 178 | ```lua 179 | … 180 | i18n.loadFile('locales/en.lua') -- English translation 181 | i18n.loadFile('locales/es.lua') -- Spanish translation 182 | i18n.loadFile('locales/fr.lua') -- French translation 183 | … 184 | ``` 185 | 186 | #### Key Points 187 | - Files must include locale key in returned table 188 | - Can be loaded in any order 189 | - Later loads override earlier translations 190 | 191 | ### Locales and Fallbacks 192 | 193 | smiti18n provides flexible locale support with automatic fallbacks and regional variants. 194 | 195 | #### Locale Naming 196 | 197 | - Pattern: `language-REGION` (e.g., 'en-US', 'es-MX', 'pt-BR') 198 | - Separator: hyphen (-) only 199 | - Not supported: underscores, spaces, or other separators 200 | 201 | #### Fallback Chain 202 | 203 | smiti18n implements a robust fallback system: 204 | 205 | 1. **Current Locale** ('es-MX') 206 | 2. **Parent Locales** (if defined, e.g., 'es-419') 207 | 3. **Root Locale** ('es') 208 | 4. **Default Value** (if provided) 209 | 5. **nil** (if no matches found) 210 | 211 | ```lua 212 | -- Example showing fallback chain 213 | i18n.load({ 214 | es = { 215 | greeting = "¡Hola!", 216 | }, 217 | ["es-MX"] = { 218 | farewell = "¡Adiós!" 219 | } 220 | }) 221 | 222 | i18n.setLocale('es-MX') 223 | print(i18n('farewell')) -- "¡Adiós!" (from es-MX) 224 | print(i18n('greeting')) -- "¡Hola!" (from es) 225 | print(i18n('missing')) -- nil (not found) 226 | print(i18n('missing', { 227 | default = 'Not found' 228 | })) -- "Not found" (default value) 229 | ``` 230 | 231 | #### Multiple Locales 232 | 233 | For handling regional variants, you can specify multiple locales in order of preference: 234 | 235 | ```lua 236 | i18n.load({ 237 | ['es-419'] = { cookie = 'galleta' }, -- Latin American 238 | ['es-ES'] = { cookie = 'galletita' }, -- European 239 | ['es'] = { thanks = 'gracias' } -- Generic 240 | }) 241 | 242 | -- Set multiple locales in priority order 243 | i18n.setLocale({'es-419', 'es-ES', 'es'}) 244 | 245 | i18n('cookie') -- Returns 'galleta' (from es-419) 246 | i18n('thanks') -- Returns 'gracias' (from es) 247 | ``` 248 | 249 | Key benefits of multiple locales: 250 | - Handle regional variations (e.g., pt-BR vs pt-PT) 251 | - Share base translations across regions 252 | - Create fallback chains (e.g., es-MX → es-419 → es) 253 | - Support partial translations with automatic fallback 254 | 255 | **💡NOTE!** Locales are tried in order of preference, with duplicates automatically removed. 256 | 257 | ### String Interpolation 258 | 259 | smiti18n supports three different styles of variable interpolation: 260 | 261 | #### Named Variables (*Recommended*) 262 | 263 | Named variables are the recommended approach as they make translations more maintainable and less error-prone. 264 | 265 | ```lua 266 | i18n.set('greeting', 'Hello %{name}, you are %{age} years old') 267 | i18n('greeting', {name = 'Alice', age = 25}) -- Hello Alice, you are 25 years old 268 | ``` 269 | #### Lua Format Specifiers 270 | ```lua 271 | i18n.set('stats', 'Score: %d, Player: %s') 272 | i18n('stats', {1000, 'Bob'}) -- Score: 1000, Player: Bob 273 | ``` 274 | #### Advanced Formatting 275 | ```lua 276 | i18n.set('profile', 'User: %.q | Age: %.d | Level: %.o') 277 | i18n('profile', { 278 | name = 'Charlie', 279 | age = 30, 280 | level = 15 281 | }) -- User: Charlie | Age: 30 | Level: 17k 282 | ``` 283 | 284 | Format modifiers: 285 | - `.q`: Quotes the value 286 | - `.d`: Decimal format 287 | - `.o`: Ordinal format 288 | 289 | ### Pluralization 290 | 291 | smiti18n implements the [CLDR plural rules](http://cldr.unicode.org/index/cldr-spec/plural-rules) for accurate pluralization across different languages. Each language can have different plural categories like 'one', 'few', 'many', and 'other'. 292 | 293 | #### Basic Usage 294 | ```lua 295 | i18n = require 'smiti18n' 296 | 297 | i18n.load({ 298 | en = { 299 | msg = { 300 | one = "one message", 301 | other = "%{count} messages" 302 | } 303 | }, 304 | ru = { 305 | msg = { 306 | one = "1 сообщение", 307 | few = "%{count} сообщения", -- 2-4 messages 308 | many = "%{count} сообщений", -- 5-20 messages 309 | other = "%{count} сообщения" -- fallback 310 | } 311 | } 312 | }) 313 | 314 | -- English pluralization 315 | i18n.setLocale('en') 316 | print(i18n('msg', {count = 1})) -- "one message" 317 | print(i18n('msg', {count = 5})) -- "5 messages" 318 | 319 | -- Russian pluralization 320 | i18n.setLocale('ru') 321 | print(i18n('msg', {count = 1})) -- "1 сообщение" 322 | print(i18n('msg', {count = 3})) -- "3 сообщения" 323 | print(i18n('msg', {count = 5})) -- "5 сообщений" 324 | ``` 325 | 326 | **💡NOTE!** The `count` parameter is required for plural translations. 327 | 328 | #### Custom Pluralization Rules 329 | 330 | For special cases or invented languages, you can define custom pluralization rules by specifying a custom pluralization function in the second parameter of `setLocale()`. 331 | 332 | ```lua 333 | -- Custom pluralization for a constructed language 334 | local customPlural = function(n) 335 | if n == 0 then return 'zero' end 336 | if n == 1 then return 'one' end 337 | if n > 1000 then return 'many' end 338 | return 'other' 339 | end 340 | 341 | i18n.setLocale('conlang', customPlural) 342 | ``` 343 | 344 | This function must return a plural category when given a number. 345 | Available plural categories: 346 | - `zero`: For languages with special handling of zero 347 | - `one`: Singular form 348 | - `two`: Special form for two items 349 | - `few`: For languages with special handling of small numbers 350 | - `many`: For languages with special handling of large numbers 351 | - `other`: Default fallback form 352 | 353 | ### Arrays 354 | 355 | Translation values can be arrays for handling ordered collections of strings with support for interpolation and pluralization. 356 | 357 | ```lua 358 | i18n.load({ 359 | en = { 360 | -- Simple array of strings 361 | greetings = {"Hello!", "Hi there!", "Howdy!"}, 362 | 363 | -- Get a random greeting 364 | print(i18n('greetings')[math.random(#i18n('greetings'))]) 365 | } 366 | }) 367 | ``` 368 | 369 | #### Features 370 | 371 | Arrays support: 372 | 373 | - Plain strings 374 | - Interpolated values 375 | - Plural forms 376 | - Nested arrays 377 | - Mixed content types 378 | 379 | #### Common Use Cases 380 | 381 | 1. **Dialogue Systems** 382 | ```lua 383 | i18n.load({ 384 | en = { 385 | dialogue = { 386 | "Detective: What brings you here?", 387 | "Witness: I saw everything %{time}.", 388 | { 389 | one = "Detective: Just %{count} witness?", 390 | other = "Detective: Already %{count} witnesses." 391 | } 392 | } 393 | } 394 | }) 395 | 396 | -- Play through dialogue sequence 397 | for _, line in ipairs(i18n('dialogue', {time = "last night", count = 1})) do 398 | print(line) 399 | end 400 | ``` 401 | 402 | 2. **Tutorial Steps** 403 | 404 | ```lua 405 | i18n.load({ 406 | en = { 407 | tutorial = { 408 | "Welcome to %{game_name}!", 409 | { 410 | one = "You have %{lives} life - be careful!", 411 | other = "You have %{lives} lives remaining." 412 | }, 413 | "Use WASD to move", 414 | "Press SPACE to jump" 415 | } 416 | } 417 | }) 418 | ``` 419 | 420 | 3. **Status Displays** 421 | 422 | ```lua 423 | i18n.load({ 424 | en = { 425 | status = { 426 | "=== Game Status ===", 427 | "Player: %{name}", 428 | { 429 | one = "%{coins} coin collected", 430 | other = "%{coins} coins collected" 431 | }, 432 | "Level: %{level}", 433 | "==================" 434 | } 435 | } 436 | }) 437 | ``` 438 | 439 | #### Tips 440 | - Arrays maintain their order 441 | - Access individual elements with numeric indices 442 | - Use `#` operator to get array length 443 | - Combine with `math.random()` for random selection 444 | - Arrays can be nested for complex dialogue trees 445 | 446 | ### Formats 447 | 448 | The library provides utilities for formatting numbers, prices and dates according to locale conventions. Formats are configured through locale files using the `_formats` key. If no locale-specific formats are defined, the library falls back to ISO standard formats. 449 | 450 | ```lua 451 | -- Example locale file (en-UK.lua) 452 | return { 453 | ["en-UK"] = { 454 | _formats = { 455 | currency = { 456 | symbol = "£", 457 | decimal_symbol = ".", 458 | thousand_separator = ",", 459 | positive_format = "%c %p%q" -- £ 99.99 460 | }, 461 | number = { 462 | decimal_symbol = ".", 463 | thousand_separator = "," 464 | }, 465 | date_time = { 466 | long_date = "%l %d %F %Y", -- Monday 25 March 2024 467 | short_time = "%H:%M" -- 15:45 468 | } 469 | } 470 | } 471 | } 472 | ``` 473 | 474 | #### Usage 475 | 476 | ```lua 477 | i18n.loadFile('locales/en-UK.lua') 478 | i18n.setLocale('en-UK') 479 | 480 | -- Numbers 481 | local num = i18n.formatNumber(1234.56) -- "1,234.56" 482 | 483 | -- Currency 484 | local price = i18n.formatPrice(99.99) -- "£ 99.99" 485 | 486 | -- Dates 487 | local date = i18n.formatDate("long_date") -- "Monday 25 March 2024" 488 | ``` 489 | 490 | #### ISO Fallbacks 491 | 492 | When no locale formats are configured, falls back to: 493 | 494 | - Numbers: ISO 31-0 (space separator, point decimal) - "1 234.56" 495 | - Currency: ISO 4217 (XXX symbol) - "XXX 99.99" 496 | - Dates: ISO 8601 - "2024-03-25T15:45:30" 497 | 498 | #### Format Patterns 499 | 500 | Dates use [strftime](https://strftime.org/) codes: `%Y` year, `%m` month, `%d` day, `%H` hour, `%M` minute. 501 | 502 | - Currency patterns use: 503 | - `%c` - currency symbol 504 | - `%q` - formatted amount 505 | - `%p` - polarity sign (+/-) 506 | 507 | For a complete reference implementation of all format options, see [spec/en-UK.lua](https://github.com/Oval-Tutu/smiti18n/blob/master/spec/en-UK.lua). 508 | 509 | ## Contributing 510 | 511 | Contributions are welcome! Please feel free to submit a pull request. 512 | 513 | ## Specs 514 | 515 | This project uses [busted](https://github.com/Olivine-Labs/busted) for its specs. If you want to run the specs, you will have to install it first. Then just execute the following from the root inspect folder: 516 | 517 | ```shell 518 | busted 519 | ``` 520 | -------------------------------------------------------------------------------- /locales/zh-SG.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["zh-SG"] = { 3 | ["Poisoned"] = "毒", 4 | ["Sound designer"] = "音响设计", 5 | ["Deity"] = "神灵", 6 | ["Production"] = "制作", 7 | ["Leg"] = "腿", 8 | ["Pause"] = "暂停", 9 | ["Multiplier"] = "倍", 10 | ["Game designer"] = "游戏设计师", 11 | ["Man"] = "男人", 12 | ["Insane"] = "疯狂", 13 | ["An error has occured."] = "发生了错误。", 14 | ["Gifts"] = "赠品", 15 | ["Tilt"] = "倾斜", 16 | ["Dungeon"] = "地下城", 17 | ["Game over!"] = "游戏结束!", 18 | ["Look"] = "看", 19 | ["Turn-based strategy"] = "回合战略", 20 | ["Junior"] = "初级", 21 | ["Programmer"] = "程序员", 22 | ["Display"] = "显示", 23 | ["Fuel"] = "燃料", 24 | ["Difficulty"] = "难度", 25 | ["Big"] = "大", 26 | ["Full Speed"] = "最高速", 27 | ["Return to Main Menu"] = "返回至主界面", 28 | ["Remember?"] = "记住", 29 | ["Planet"] = "行星", 30 | ["Class"] = "类", 31 | ["Splitscreen"] = "分屏", 32 | ["In-app purchase"] = "在应用程序内购买", 33 | ["Save Game"] = "保存欧系", 34 | ["Shake"] = "震动", 35 | ["Sound Options"] = "声音设置", 36 | ["Lap"] = "全程", 37 | ["Easy"] = "简单", 38 | ["Special thanks"] = "特别感谢", 39 | ["Adventure game"] = "冒险游戏", 40 | ["No games found."] = "找不到游戏。", 41 | ["Animation"] = "动画", 42 | ["Escape"] = "逃生", 43 | ["You won!"] = "你赢了!", 44 | ["Previous track"] = "上一曲目", 45 | ["Kills"] = "击杀", 46 | ["Database Admin"] = "三维建模", 47 | ["Second place"] = "第二名", 48 | ["Previous"] = "返回", 49 | ["Wins"] = "获胜", 50 | ["More"] = "更多", 51 | ["Voice volume"] = "声音音量", 52 | ["Warning"] = "注意", 53 | ["Monster"] = "怪兽", 54 | ["FPS"] = "FPS", 55 | ["Close"] = "关闭", 56 | ["Wet"] = ".湿", 57 | ["Voice actor"] = "配音演员", 58 | ["Strategy game"] = "战略游戏", 59 | ["Script writer"] = "剧本", 60 | ["Video Options"] = "视频设置", 61 | ["Exit"] = "退出", 62 | ["Exit?"] = "退出?", 63 | ["Head"] = "头", 64 | ["Load"] = "载入", 65 | ["Heal"] = "愈合", 66 | ["Dragons"] = "龙", 67 | ["Exit to Desktop"] = "退出至桌面", 68 | ["Hit points"] = "生命值", 69 | ["Age"] = "年龄", 70 | ["Tactics"] = "战术", 71 | ["Game developer"] = "游戏开发者", 72 | ["Adventure"] = "冒险", 73 | ["Nose"] = "鼻子", 74 | ["Login"] = "登录", 75 | ["Invalid name!"] = "名称无效!", 76 | ["You have been defeated."] = "你被击败了。", 77 | ["Local Multiplayer"] = "本地联机", 78 | ["Music"] = "音乐", 79 | ["Kill"] = "击杀", 80 | ["Landing"] = "降落", 81 | ["Talk"] = "谈话", 82 | ["Name"] = "名称", 83 | ["Training"] = "训练", 84 | ["Programmers"] = "程序员", 85 | ["Respawn"] = "重生", 86 | ["Ghost"] = "鬼", 87 | ["Network Options"] = "网络设置", 88 | ["Click"] = "点击", 89 | ["Finger"] = "手指", 90 | ["Pistol"] = "手枪", 91 | ["Quiz game"] = "问答游戏", 92 | ["Gift"] = "赠品", 93 | ["Effect detail"] = "效果细节", 94 | ["Air"] = "风", 95 | ["Hips"] = "臀部", 96 | ["New Game"] = "新游戏", 97 | ["Save file corrupted."] = "存档文件已被破坏。", 98 | ["Programming"] = "编程", 99 | ["Play Online"] = "在线游戏", 100 | ["Writer"] = "文案", 101 | ["Chief Technical Officer"] = "首席技术官", 102 | ["Mail"] = "邮件", 103 | ["Skill"] = "技能", 104 | ["Share"] = "分享", 105 | ["Action game"] = "动作游戏", 106 | ["Spread"] = "扩", 107 | ["Defeat"] = "失败", 108 | ["Inventory Capacity"] = "装备容量", 109 | ["Windowed"] = "窗口模式", 110 | ["Drag and drop"] = "拖放", 111 | ["Mission Objectives"] = "任务目标", 112 | ["Please wait..."] = "请消侯等待...", 113 | ["HMD orientation reset"] = "HMD方向重置", 114 | ["Ammunition"] = "弹药值", 115 | ["Wounded"] = "受伤", 116 | ["Shield"] = "盾", 117 | ["Endurance"] = "耐力", 118 | ["Silver medal"] = "银徽章", 119 | ["Play"] = "开始", 120 | ["Huge"] = "极大", 121 | ["Wood"] = "木", 122 | ["Size"] = "大小", 123 | ["Fire"] = "火", 124 | ["Dragon"] = "龙", 125 | ["Continue"] = "继续", 126 | ["Fur"] = "毛皮", 127 | ["Wings"] = "机翼", 128 | ["Thorax"] = "胸部", 129 | ["Mouth"] = "嘴巴", 130 | ["Fonts"] = "字体", 131 | ["Spell"] = "咒语", 132 | ["Heart"] = "心", 133 | ["Critical Hit"] = "严重伤害", 134 | ["Ears"] = "耳朵", 135 | ["Are you really sure?"] = "你是否确认?", 136 | ["Max"] = "最高限度", 137 | ["Casual game"] = "休闲游戏", 138 | ["Bow"] = "弓", 139 | ["Image"] = "图像", 140 | ["Priest"] = "祭士", 141 | ["Objective"] = "目标", 142 | ["Metal"] = "金", 143 | ["Shields"] = "盾", 144 | ["Recordist"] = "录音师", 145 | ["Rifle"] = "步枪", 146 | ["Zombies"] = "僵尸", 147 | ["Sniper rifle"] = "狙击步枪", 148 | ["Neck"] = "颈", 149 | ["Color"] = "颜色", 150 | ["You are dead."] = "你死了。", 151 | ["Brakes"] = "煞车闸", 152 | ["Boost"] = "提升", 153 | ["Project Manager"] = "项目经理", 154 | ["Return"] = "返回", 155 | ["Main Menu"] = "主界面", 156 | ["Shadow"] = "影子", 157 | ["Steering"] = "转向", 158 | ["Spin"] = "旋转", 159 | ["Sprint"] = "冲刺", 160 | ["Fantasy game"] = "幻想游戏", 161 | ["Card"] = "卡牌", 162 | ["Science fiction game"] = "科幻游戏", 163 | ["Female"] = "女性", 164 | ["Small"] = "小", 165 | ["Your team lost!"] = "你的团队失败", 166 | ["Bullets"] = "子弹", 167 | ["Challenge"] = "挑战", 168 | ["Swipe"] = "滑动", 169 | ["Help"] = "帮助", 170 | ["Handling"] = "操纵", 171 | ["Level up!"] = "升级", 172 | ["Position"] = "地位", 173 | ["Water"] = "水", 174 | ["Medal"] = "徽章", 175 | ["Foley artist"] = "音效师", 176 | ["Level design"] = "关卡设计", 177 | ["Animator"] = "动画师", 178 | ["Half Speed"] = "半速度", 179 | ["Platformer game"] = "平台游戏", 180 | ["Incomplete"] = "未完成", 181 | ["Energy shield"] = "能量罩", 182 | ["Mix"] = "混合", 183 | ["Trial"] = "试用版", 184 | ["Sports game"] = "体育游戏", 185 | ["Images"] = "图像", 186 | ["Technical Director"] = "技术主任", 187 | ["Continue?"] = "继续?", 188 | ["Loser"] = "输家", 189 | ["Mouse sensitivity"] = "鼠标灵敏度", 190 | ["Publisher"] = "出版商", 191 | ["Sound effect volume"] = "音效音量", 192 | ["Bronze medal"] = "铜徽章", 193 | ["Ammo"] = "弹药", 194 | ["Camera Y-Axis"] = "摄影机Y坐标轴", 195 | ["Woman"] = "女人", 196 | ["Complete"] = "完成", 197 | ["Destroy"] = "破坏", 198 | ["Save"] = "保存", 199 | ["Run"] = "奔跑", 200 | ["Language"] = "语言", 201 | ["Test Manager"] = "测试经理", 202 | ["Warrior"] = "武士", 203 | ["Third Person View"] = "第三人称视角", 204 | ["Steer"] = "左右", 205 | ["Tiny"] = "极小", 206 | ["Min"] = "最少限度", 207 | ["Real-time strategy"] = "即时战略", 208 | ["HUD"] = "HUD", 209 | ["Tower defence game"] = "塔防游戏", 210 | ["Scroll"] = "滚动", 211 | ["Go to"] = "去", 212 | ["Dodge"] = "闪避", 213 | ["Chest"] = "胸", 214 | ["Platinum"] = "白金", 215 | ["Save data"] = "保存数据", 216 | ["Critical Miss"] = "严重失误", 217 | ["Saving..."] = "保存中…", 218 | ["Women"] = "女人", 219 | ["Treasure"] = "财宝", 220 | ["Tap"] = "触摸", 221 | ["Dead zone"] = "危险地区", 222 | ["Graphic designer"] = "图像设计", 223 | ["Kill Assist"] = "杀灭协助", 224 | ["Anti-aliasing"] = "抗折叠", 225 | ["Font"] = "字体", 226 | ["Sell"] = "销售", 227 | ["Die"] = "骰子", 228 | ["Model detail"] = "模型细节", 229 | ["Build"] = "建设", 230 | ["Ear"] = "耳", 231 | ["Credits"] = "功劳", 232 | ["High score"] = "最高评分", 233 | ["Very Hard"] = "非常困难", 234 | ["Confirm"] = "确认", 235 | ["Ultra"] = "非常高", 236 | ["Music Player"] = "音乐播放器", 237 | ["Concept artist"] = "概念美术", 238 | ["Stunned"] = "愕然", 239 | ["Crouch"] = "蹲", 240 | ["Producer"] = "监制", 241 | ["Version"] = "版本", 242 | ["Simulation game"] = "模拟游戏", 243 | ["Pinch"] = "捏", 244 | ["Collect"] = "收取", 245 | ["Please be careful."] = "请注意!", 246 | ["New Character"] = "创新角色", 247 | ["Premium"] = "超值版", 248 | ["Translation"] = "翻译", 249 | ["Critical"] = "瀕死", 250 | ["Respawn in:"] = "于此之后重生:", 251 | ["Damage"] = "破坏率", 252 | ["Arrow"] = "箭", 253 | ["Download"] = "下载", 254 | ["Register"] = "注册", 255 | ["Knife"] = "小刀", 256 | ["Downloadable content"] = "下载包", 257 | ["Online Multiplayer"] = "在线联机", 258 | ["Normal"] = "标准", 259 | ["Run away"] = "逃跑", 260 | ["Story"] = "故事", 261 | ["Shader detail"] = "光影细节", 262 | ["Bet"] = "赌", 263 | ["Press Start"] = "按下开始", 264 | ["Yeah"] = "好的", 265 | ["DLC"] = "DLC", 266 | ["Shadows"] = "阴影效果", 267 | ["Shoot"] = "射击", 268 | ["Bonus"] = "奖金", 269 | ["You lost!"] = "你输了!", 270 | ["Dice"] = "骰子", 271 | ["Castle"] = "城", 272 | ["Back"] = "返回", 273 | ["Forgot password"] = "忘记密码", 274 | ["Eyes"] = "眼睛", 275 | ["Claim"] = "索取", 276 | ["Frozen"] = "凍結", 277 | ["Gear"] = "齿轮", 278 | ["Victory"] = "胜利", 279 | ["Invalid CD Key."] = "序列号无效。", 280 | ["Tester"] = "测试员", 281 | ["Feet"] = "双脚", 282 | ["Paused"] = "暂停中", 283 | ["Design Director"] = "设计总监", 284 | ["Alien"] = "外星人", 285 | ["Last Name"] = "姓", 286 | ["First place"] = "第一名", 287 | ["Hearts"] = "心", 288 | ["Developed by"] = "游戏开发由", 289 | ["Machine Gun"] = "机关枪", 290 | ["Mission Objective"] = "任务目标", 291 | ["Assists"] = "协助", 292 | ["Purchase"] = "购买", 293 | ["Program Manager"] = "规划经理", 294 | ["Senior"] = "高级", 295 | ["Thank you!"] = "谢谢!", 296 | ["Artists"] = "美术师", 297 | ["Interface Artist"] = "影片美术", 298 | ["Drop"] = "放下", 299 | ["Rocket Launcher"] = "火箭炮", 300 | ["Hammer"] = "铁锤", 301 | ["Suspension"] = "悬挂", 302 | ["Lead"] = "领导", 303 | ["Sniper"] = "狙击射手", 304 | ["Virtual Reality"] = "虚拟现实", 305 | ["VR comfort mode"] = "虚拟现实舒适模式", 306 | ["Yes"] = "是", 307 | ["Key"] = "关键", 308 | ["Shareware"] = "共享软件", 309 | ["Medium"] = "中", 310 | ["Princess"] = "公主", 311 | ["Gauntlets"] = "铁手套", 312 | ["Hard"] = "困难", 313 | ["Full"] = "完整版", 314 | ["Deaths"] = "死亡", 315 | ["Demo"] = "试玩版", 316 | ["Press any key to continue"] = "按下任意键以继续", 317 | ["Visual Effects"] = "视觉效果", 318 | ["Goodbye!"] = "再见!", 319 | ["Drive"] = "驱动", 320 | ["Very High"] = "非常高", 321 | ["Animation Director"] = "动画总监", 322 | ["Low"] = "低", 323 | ["Test Lead"] = "测试组长", 324 | ["High"] = "高", 325 | ["Widescreen"] = "宽屏幕", 326 | ["Third place"] = "第三名", 327 | ["V-sync"] = "垂直同步", 328 | ["Load Game"] = "载入游戏", 329 | ["Winner"] = "赢家", 330 | ["Foot"] = "脚", 331 | ["Quit"] = "退出", 332 | ["Volume"] = "音量", 333 | ["Demon"] = "魔鬼", 334 | ["Inventory"] = "装备栏", 335 | ["Quality"] = "质量", 336 | ["Level"] = "级别", 337 | ["Music volume"] = "音乐音量", 338 | ["Multicore rendering"] = "多核渲染", 339 | ["Graphics Options"] = "图形设置", 340 | ["Weapon"] = "武器", 341 | ["Manuscript"] = "手稿", 342 | ["Capture"] = "捉取", 343 | ["Director"] = "总监", 344 | ["Gameplay Options"] = "游戏设置", 345 | ["Fullscreen"] = "全屏", 346 | ["Art Director"] = "美术总监", 347 | ["FOV"] = "视场角", 348 | ["Skeleton"] = "尸骨", 349 | ["First Person View"] = "第一人称视角", 350 | ["Trilinear"] = "三线性", 351 | ["Down"] = "下", 352 | ["Filtering mode"] = "过滤模式", 353 | ["Cannot connect to server."] = "不能连接至服务器。", 354 | ["Encumbrance"] = "负担", 355 | ["Advanced Graphics"] = "先进的图形", 356 | ["Anisotropic"] = "异向", 357 | ["Difficulty Options"] = "难度设置", 358 | ["Use"] = "使用", 359 | ["Controls"] = "操作模式", 360 | ["Your team won!"] = "你的团队胜利", 361 | ["Bloom"] = "盛开", 362 | ["Options"] = "设置", 363 | ["Username"] = "用户名", 364 | ["Read"] = "阅览", 365 | ["Instructions"] = "说明", 366 | ["Gamepad"] = "游戏手柄", 367 | ["Clone"] = "复制", 368 | ["Mouse"] = "鼠标", 369 | ["First Name"] = "名字", 370 | ["Arrows"] = "箭", 371 | ["Space"] = "宇宙", 372 | ["Versus"] = "对抗模式", 373 | ["Jump"] = "跳", 374 | ["Tutorial"] = "教程", 375 | ["Cook"] = "煮", 376 | ["Deathmatch"] = "死亡竞赛", 377 | ["Cooperative"] = "合作模式", 378 | ["Special thanks to"] = "特别感谢", 379 | ["Co-op"] = "合作", 380 | ["Challenge mode"] = "挑战模式", 381 | ["Password"] = "密码", 382 | ["Hardcore game"] = "硬核游戏", 383 | ["English"] = "Simplified Chinese", 384 | ["Epic"] = "史诗的", 385 | ["YES"] = "是", 386 | ["ltr"] = "ltr", 387 | ["Arm"] = "臂", 388 | ["World"] = "世界", 389 | ["Lock"] = "楗", 390 | ["Voices"] = "声音", 391 | ["Video"] = "视频设置", 392 | ["Unlock"] = "开锁", 393 | ["Sound"] = "声音", 394 | ["Cancel"] = "取消", 395 | ["Match"] = "比赛", 396 | ["Tournament"] = "比赛", 397 | ["Skip"] = "跳过", 398 | ["Return to Main Menu?"] = "返回至主界面?", 399 | ["Replay"] = "重播", 400 | ["Impossible"] = "不可能", 401 | ["Quit?"] = "退出?", 402 | ["Press any key"] = "按下任意键", 403 | ["Replace"] = "更换", 404 | ["Are you sure you want to quit?"] = "你确定你需要退出吗?", 405 | ["Texture detail"] = "材质细节", 406 | ["Medic"] = "军医助手", 407 | ["Free"] = "免费版", 408 | ["Price"] = "价钱", 409 | ["Double-click"] = "双击", 410 | ["Lite"] = "位版本", 411 | ["Hand"] = "手", 412 | ["Energy shields"] = "能量罩", 413 | ["Cheats detected!"] = "检测到作弊!", 414 | ["Error code:"] = "错误代码:", 415 | ["Connection lost."] = "网络连接失败。", 416 | ["3D Modeling"] = "三维建模", 417 | ["Soundtrack"] = "原声音乐", 418 | ["Coin"] = "硬币", 419 | ["Background music"] = "背景音乐", 420 | ["You win!"] = "你赢了!", 421 | ["Speed"] = "速度", 422 | ["Climb"] = "爬上", 423 | ["Indie"] = "独立", 424 | ["Quest"] = "探索", 425 | ["No HMD detected"] = "未检测到HMD", 426 | ["Camera"] = "摄影机", 427 | ["Prince"] = "王子", 428 | ["Goddess"] = "女神", 429 | ["Game design"] = "游戏设计", 430 | ["Wizard"] = "巫师", 431 | ["Delete Character"] = "删除角色", 432 | ["Button"] = "按键", 433 | ["Demonness"] = "女魔头", 434 | ["The other player has disconnected."] = "另一个玩家断开了连接。", 435 | ["Cinematics Director"] = "影片导演", 436 | ["Inverted"] = "反转", 437 | ["All"] = "全部", 438 | ["Audio Director"] = "音乐总监", 439 | ["Code"] = "代码", 440 | ["Chapter"] = "章", 441 | ["Attack"] = "攻击", 442 | ["Silver"] = "銀", 443 | ["Cinematic Animator"] = "影片动画", 444 | ["Are you sure?"] = "你确定吗?", 445 | ["Camera X-Axis"] = "摄影机X坐标轴", 446 | ["NO"] = "否", 447 | ["Staff"] = "杖", 448 | ["Go"] = "前往", 449 | ["Models"] = "模型", 450 | ["Inn"] = "客栈", 451 | ["Hair"] = "头发", 452 | ["Death"] = "死亡", 453 | ["Keyboard"] = "键盘", 454 | ["Fly"] = "飞", 455 | ["Spaceship"] = "宇宙飞船", 456 | ["Cards"] = "卡片", 457 | ["Pick up"] = "拾起", 458 | ["Locked"] = "锁定", 459 | ["Exit to Desktop?"] = "退出至桌面?", 460 | ["Gun"] = "枪", 461 | ["RPG"] = "RPG", 462 | ["Cast"] = "施咒语", 463 | ["Your opponent has disconnected."] = "你的对手断开连接。", 464 | ["Be careful!"] = "注意", 465 | ["Genre"] = "类型", 466 | ["Arms"] = "臂", 467 | ["Assist"] = "协助", 468 | ["Bronze"] = "銅", 469 | ["Power-up"] = "提升功率", 470 | ["Mission"] = "任务", 471 | ["Item"] = "物品", 472 | ["Robot"] = "机器人", 473 | ["Ninja"] = "忍者", 474 | ["Inventory Full"] = "装备已满", 475 | ["Mage"] = "魔法师", 476 | ["Earth"] = "地球", 477 | ["The End"] = "结束", 478 | ["Assistant"] = "助理", 479 | ["Page"] = "页", 480 | ["Left"] = "左", 481 | ["Sword"] = "剑", 482 | ["Shotgun"] = "散弹枪", 483 | ["Pirate"] = "海贼", 484 | ["Shooter game"] = "射击游戏", 485 | ["Artificial Intelligence"] = "人工智能", 486 | ["Miss"] = "失误", 487 | ["Puzzle game"] = "拼图游戏", 488 | ["Lives"] = "生命", 489 | ["Dagger"] = "短剑", 490 | ["Soldier"] = "战士", 491 | ["Hit"] = "暴击", 492 | ["Creative Director"] = "创意总监", 493 | ["Game"] = "游戏", 494 | ["Tournaments"] = "比赛", 495 | ["Armor"] = "护甲", 496 | ["Composer"] = "作曲", 497 | ["Door"] = "门", 498 | ["Multiplayer"] = "联机模式", 499 | ["Voice acting"] = "配音", 500 | ["Craft"] = "技术", 501 | ["Discard"] = "抛弃", 502 | ["Gloves"] = "手套", 503 | ["Slowed"] = "減速", 504 | ["Sneak"] = "潜行", 505 | ["Experience points"] = "经验值", 506 | ["Next track"] = "下一个曲目", 507 | ["Walk"] = "步行", 508 | ["Takeoff"] = "腾飞", 509 | ["Chassis"] = "马车", 510 | ["Gem"] = "宝石", 511 | ["Burning"] = "燃烧", 512 | ["Wheels"] = "轮子", 513 | ["Book"] = "书", 514 | ["Cyborg"] = "机器人", 515 | ["Sound engineer"] = "音响工程师", 516 | ["Altitude"] = "高度", 517 | ["Gyroscope"] = "回转仪", 518 | ["Magic"] = "魔法", 519 | ["Wand"] = "权杖", 520 | ["Helmet"] = "钢盔", 521 | ["Unhurt"] = "未受伤", 522 | ["Race"] = "竞赛", 523 | ["Art gallery"] = "艺术馆", 524 | ["No open games."] = "没有招募中的游戏", 525 | ["Very Easy"] = "非常简单", 526 | ["Technical artist"] = "技术美术", 527 | ["Open"] = "开放", 528 | ["Throw"] = "扔", 529 | ["Character Designer"] = "角色设计", 530 | ["Time"] = "时间", 531 | ["The button"] = "按键", 532 | ["Cave"] = "洞穴", 533 | ["Spawn Point"] = "重生点", 534 | ["Love"] = "爱", 535 | ["Laps"] = "圈数", 536 | ["You cannot carry any more."] = "你不能再拿起东西了。", 537 | ["Rotate"] = "环绕", 538 | ["Resolution"] = "解析度", 539 | ["Lead programmer"] = "程序组长", 540 | ["You lose!"] = "你输了!", 541 | ["Misc."] = "其它", 542 | ["Gods"] = "神", 543 | ["Enemy"] = "敌人", 544 | ["Beard"] = "胡子", 545 | ["Ingot"] = "铁块", 546 | ["Associate"] = "副", 547 | ["Graphics"] = "图形设置", 548 | ["Extras"] = "演员", 549 | ["Singleplayer"] = "单人模式", 550 | ["No {0} detected"] = "未检测到{0}", 551 | ["Medieval game"] = "中世纪式游戏", 552 | ["Bomb"] = "炸弹", 553 | ["Gold"] = "金", 554 | ["Thief"] = "盗贼", 555 | ["Nope"] = "不行", 556 | ["Buy"] = "购买", 557 | ["Bullet"] = "子弹", 558 | ["Bilinear"] = "双线性", 559 | ["Gold medal"] = "金徽章", 560 | ["Respawning"] = "重生中", 561 | ["Retro game"] = "复古游戏", 562 | ["Weapons"] = "武器", 563 | ["Musician"] = "音乐师", 564 | ["Sound Effects"] = "音响效果", 565 | ["Defend"] = "防守", 566 | ["Junk"] = "废物的", 567 | ["GAME OVER!"] = "游戏结束!", 568 | ["God"] = "神", 569 | ["Art"] = "美术", 570 | ["Reset save data?"] = "重设已保存数据", 571 | ["Rank"] = "行列", 572 | ["Losses"] = "失败", 573 | ["Dead"] = "死亡", 574 | ["Boots"] = "靴", 575 | ["Round"] = "回合", 576 | ["E-mail"] = "电子邮件", 577 | ["Male"] = "男性", 578 | ["Welcome"] = "欢迎", 579 | ["No"] = "否", 580 | ["The key"] = "关键", 581 | ["Your teammate has disconnected."] = "你的队友断开了连接。", 582 | ["You died."] = "你死了。", 583 | ["Board"] = "盘", 584 | ["Skin"] = "皮肤", 585 | ["Game development"] = "游戏开发", 586 | ["Transgender"] = "跨性别", 587 | ["Leaving tracking area"] = "无信号", 588 | ["Artist"] = "美术师", 589 | ["Score"] = "评分", 590 | ["Localization"] = "本地化", 591 | ["Objectives"] = "目标", 592 | ["Unconscious"] = "失去知觉", 593 | ["Zombie"] = "僵尸", 594 | ["Eye"] = "眼", 595 | ["Level designer"] = "关卡设计师", 596 | ["Men"] = "男人", 597 | ["OK"] = "OK", 598 | ["Jackpot"] = "头奖", 599 | ["Right"] = "右", 600 | ["Chin"] = "下巴", 601 | ["Translated by the Polyglot Project"] = "Polyglot 项目提供翻译", 602 | ["Hands"] = "手", 603 | ["Rusty"] = "生疏的", 604 | ["Roleplaying game"] = "角色扮演游戏", 605 | ["Press Start to continue"] = "按下开始以继续", 606 | ["Play again"] = "再玩一次", 607 | ["Racing"] = "竞速", 608 | ["Loading..."] = "正在登录中...", 609 | ["Drag"] = "拖", 610 | ["Respawn?"] = "重生?", 611 | ["Time left"] = "剩余时间", 612 | ["Video Quality"] = "视频质量", 613 | ["Enemies"] = "敌人", 614 | ["Legs"] = "双腿", 615 | ["Health"] = "健康值", 616 | ["Place"] = "空间", 617 | ["Up"] = "上", 618 | ["Next"] = "下一个", 619 | ["Depth"] = "深度", 620 | } 621 | } 622 | -------------------------------------------------------------------------------- /locales/zh-MO.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["zh-MO"] = { 3 | ["Poisoned"] = "中毒", 4 | ["Sound designer"] = "音響設計師", 5 | ["Deity"] = "神靈", 6 | ["Production"] = "制作", 7 | ["Leg"] = "腿", 8 | ["Pause"] = "暫停", 9 | ["Multiplier"] = "倍", 10 | ["Game designer"] = "遊戲設計師", 11 | ["Man"] = "男人", 12 | ["Insane"] = "瘋狂", 13 | ["An error has occured."] = "發生了錯誤。", 14 | ["Gifts"] = "贈品", 15 | ["Tilt"] = "傾斜", 16 | ["Dungeon"] = "地下城", 17 | ["Game over!"] = "游戲結束!", 18 | ["Look"] = "看", 19 | ["Turn-based strategy"] = "回合戰略遊戲", 20 | ["Junior"] = "初級", 21 | ["Programmer"] = "程序員", 22 | ["Display"] = "顯示", 23 | ["Fuel"] = "燃料", 24 | ["Difficulty"] = "難度", 25 | ["Big"] = "大", 26 | ["Full Speed"] = "急速", 27 | ["Return to Main Menu"] = "返回至主界面", 28 | ["Remember?"] = "記住", 29 | ["Planet"] = "行星", 30 | ["Class"] = "角色類", 31 | ["Splitscreen"] = "分屏", 32 | ["In-app purchase"] = "在應用程序內購買", 33 | ["Save Game"] = "保存歐系", 34 | ["Shake"] = "震動", 35 | ["Sound Options"] = "聲音設置", 36 | ["Lap"] = "全程", 37 | ["Easy"] = "簡單", 38 | ["Special thanks"] = "特別感謝", 39 | ["Adventure game"] = "冒險游戲", 40 | ["No games found."] = "找不到游戲。", 41 | ["Animation"] = "動畫", 42 | ["Escape"] = "逃生", 43 | ["You won!"] = "你贏了!", 44 | ["Previous track"] = "上一曲目", 45 | ["Kills"] = "擊殺", 46 | ["Database Admin"] = "數據庫管理員", 47 | ["Second place"] = "第二名", 48 | ["Previous"] = "返回", 49 | ["Wins"] = "獲勝", 50 | ["More"] = "更多", 51 | ["Voice volume"] = "聲音音量", 52 | ["Warning"] = "注意", 53 | ["Monster"] = "怪獸", 54 | ["FPS"] = "FPS", 55 | ["Close"] = "關閉", 56 | ["Wet"] = ".濕", 57 | ["Voice actor"] = "配音演員", 58 | ["Strategy game"] = "戰略游戲", 59 | ["Script writer"] = "劇本寫作人", 60 | ["Video Options"] = "視頻設置", 61 | ["Exit"] = "退出", 62 | ["Exit?"] = "退出?", 63 | ["Head"] = "頭", 64 | ["Load"] = "載入", 65 | ["Heal"] = "愈合", 66 | ["Dragons"] = "龍", 67 | ["Exit to Desktop"] = "退出至桌面", 68 | ["Hit points"] = "生命值", 69 | ["Age"] = "年齡", 70 | ["Tactics"] = "戰術", 71 | ["Game developer"] = "遊戲開發者", 72 | ["Adventure"] = "冒險", 73 | ["Nose"] = "鼻子", 74 | ["Login"] = "登錄", 75 | ["Invalid name!"] = "名稱無效!", 76 | ["You have been defeated."] = "你被擊敗了。", 77 | ["Local Multiplayer"] = "本地聯機", 78 | ["Music"] = "音樂", 79 | ["Kill"] = "擊殺", 80 | ["Landing"] = "降落", 81 | ["Talk"] = "談話", 82 | ["Name"] = "名稱", 83 | ["Training"] = "訓練", 84 | ["Programmers"] = "程序員", 85 | ["Respawn"] = "重生", 86 | ["Ghost"] = "鬼", 87 | ["Network Options"] = "網絡設置", 88 | ["Click"] = "點擊", 89 | ["Finger"] = "手指", 90 | ["Pistol"] = "手槍", 91 | ["Quiz game"] = "問答游戲", 92 | ["Gift"] = "贈品", 93 | ["Effect detail"] = "效果細節", 94 | ["Air"] = "風", 95 | ["Hips"] = "臀部", 96 | ["New Game"] = "新游戲", 97 | ["Save file corrupted."] = "存檔文件已被破壞。", 98 | ["Programming"] = "編程", 99 | ["Play Online"] = "在線游戲", 100 | ["Writer"] = "寫作人", 101 | ["Chief Technical Officer"] = "首席技術官", 102 | ["Mail"] = "郵件", 103 | ["Skill"] = "技能", 104 | ["Share"] = "分享", 105 | ["Action game"] = "動作游戲", 106 | ["Spread"] = "擴", 107 | ["Defeat"] = "失敗", 108 | ["Inventory Capacity"] = "裝備容量", 109 | ["Windowed"] = "窗口模式", 110 | ["Drag and drop"] = "拖放", 111 | ["Mission Objectives"] = "任務目標", 112 | ["Please wait..."] = "請消侯等待...", 113 | ["HMD orientation reset"] = "HMD方向重置", 114 | ["Ammunition"] = "彈藥值", 115 | ["Wounded"] = "受傷", 116 | ["Shield"] = "盾", 117 | ["Endurance"] = "耐力", 118 | ["Silver medal"] = "銀徽章", 119 | ["Play"] = "開始", 120 | ["Huge"] = "極大", 121 | ["Wood"] = "木", 122 | ["Size"] = "大小", 123 | ["Fire"] = "火", 124 | ["Dragon"] = "龍", 125 | ["Continue"] = "繼續", 126 | ["Fur"] = "毛皮", 127 | ["Wings"] = "翼", 128 | ["Thorax"] = "胸部", 129 | ["Mouth"] = "嘴巴", 130 | ["Fonts"] = "字型", 131 | ["Spell"] = "咒語", 132 | ["Heart"] = "心", 133 | ["Critical Hit"] = "嚴重傷害", 134 | ["Ears"] = "耳朵", 135 | ["Are you really sure?"] = "你是否確認?", 136 | ["Max"] = "最高限度", 137 | ["Casual game"] = "休閑游戲", 138 | ["Bow"] = "弓", 139 | ["Image"] = "圖像", 140 | ["Priest"] = "祭士", 141 | ["Objective"] = "目標", 142 | ["Metal"] = "金", 143 | ["Shields"] = "盾", 144 | ["Recordist"] = "錄音師", 145 | ["Rifle"] = "步槍", 146 | ["Zombies"] = "僵尸", 147 | ["Sniper rifle"] = "狙擊步槍", 148 | ["Neck"] = "頸", 149 | ["Color"] = "顏色", 150 | ["You are dead."] = "你死了。", 151 | ["Brakes"] = "煞車閘", 152 | ["Boost"] = "提升", 153 | ["Project Manager"] = "項目經理", 154 | ["Return"] = "返回", 155 | ["Main Menu"] = "主界面", 156 | ["Shadow"] = "影子", 157 | ["Steering"] = "轉向", 158 | ["Spin"] = "旋轉", 159 | ["Sprint"] = "沖刺", 160 | ["Fantasy game"] = "魔幻遊戲", 161 | ["Card"] = "卡牌遊戲", 162 | ["Science fiction game"] = "科幻游戲", 163 | ["Female"] = "女性", 164 | ["Small"] = "小", 165 | ["Your team lost!"] = "你的團隊失敗", 166 | ["Bullets"] = "子彈", 167 | ["Challenge"] = "挑戰", 168 | ["Swipe"] = "滑動", 169 | ["Help"] = "幫助", 170 | ["Handling"] = "操縱", 171 | ["Level up!"] = "升級", 172 | ["Position"] = "地位", 173 | ["Water"] = "水", 174 | ["Medal"] = "徽章", 175 | ["Foley artist"] = "擬音藝術家", 176 | ["Level design"] = "關卡設計", 177 | ["Animator"] = "動畫師", 178 | ["Half Speed"] = "半速", 179 | ["Platformer game"] = "平台游戲", 180 | ["Incomplete"] = "未完成", 181 | ["Energy shield"] = "能量罩", 182 | ["Mix"] = "混合", 183 | ["Trial"] = "試用版", 184 | ["Sports game"] = "體育游戲", 185 | ["Images"] = "圖像", 186 | ["Technical Director"] = "技術主任", 187 | ["Continue?"] = "繼續?", 188 | ["Loser"] = "輸家", 189 | ["Mouse sensitivity"] = "鼠標靈敏度", 190 | ["Publisher"] = "出版商", 191 | ["Sound effect volume"] = "音效音量", 192 | ["Bronze medal"] = "銅徽章", 193 | ["Ammo"] = "彈藥", 194 | ["Camera Y-Axis"] = "攝影機Y坐標軸", 195 | ["Woman"] = "女人", 196 | ["Complete"] = "完成", 197 | ["Destroy"] = "消滅", 198 | ["Save"] = "保存", 199 | ["Run"] = "奔跑", 200 | ["Language"] = "語言", 201 | ["Test Manager"] = "測試經理", 202 | ["Warrior"] = "武士", 203 | ["Third Person View"] = "第三人稱視角", 204 | ["Steer"] = "左右", 205 | ["Tiny"] = "極小", 206 | ["Min"] = "最低限度", 207 | ["Real-time strategy"] = "即時戰略遊戲", 208 | ["HUD"] = "HUD", 209 | ["Tower defence game"] = "塔防游戲", 210 | ["Scroll"] = "滾動", 211 | ["Go to"] = "去", 212 | ["Dodge"] = "閃避", 213 | ["Chest"] = "胸", 214 | ["Platinum"] = "白金", 215 | ["Save data"] = "保存數據", 216 | ["Critical Miss"] = "嚴重失誤", 217 | ["Saving..."] = "保存中…", 218 | ["Women"] = "女人", 219 | ["Treasure"] = "財寶", 220 | ["Tap"] = "觸摸", 221 | ["Dead zone"] = "危險地區", 222 | ["Graphic designer"] = "圖像設計", 223 | ["Kill Assist"] = "助殺", 224 | ["Anti-aliasing"] = "抗折疊", 225 | ["Font"] = "字型", 226 | ["Sell"] = "銷售", 227 | ["Die"] = "骰子", 228 | ["Model detail"] = "模型細節", 229 | ["Build"] = "建設", 230 | ["Ear"] = "耳", 231 | ["Credits"] = "製作群", 232 | ["High score"] = "最高分", 233 | ["Very Hard"] = "非常困難", 234 | ["Confirm"] = "確認", 235 | ["Ultra"] = "最高", 236 | ["Music Player"] = "音樂播放器", 237 | ["Concept artist"] = "觀念美術", 238 | ["Stunned"] = "愕然", 239 | ["Crouch"] = "蹲", 240 | ["Producer"] = "監制", 241 | ["Version"] = "版本", 242 | ["Simulation game"] = "模擬游戲", 243 | ["Pinch"] = "捏", 244 | ["Collect"] = "收取", 245 | ["Please be careful."] = "請注意!", 246 | ["New Character"] = "創新角色", 247 | ["Premium"] = "超值版", 248 | ["Translation"] = "翻譯", 249 | ["Critical"] = "瀕死", 250 | ["Respawn in:"] = "於此之后重生:", 251 | ["Damage"] = "破壞率", 252 | ["Arrow"] = "箭", 253 | ["Download"] = "下載", 254 | ["Register"] = "注冊", 255 | ["Knife"] = "小刀", 256 | ["Downloadable content"] = "下載內容", 257 | ["Online Multiplayer"] = "在線聯機", 258 | ["Normal"] = "標准", 259 | ["Run away"] = "逃跑", 260 | ["Story"] = "故事", 261 | ["Shader detail"] = "Shader 細節", 262 | ["Bet"] = "賭", 263 | ["Press Start"] = "按下開始", 264 | ["Yeah"] = "好的", 265 | ["DLC"] = "DLC", 266 | ["Shadows"] = "陰影效果", 267 | ["Shoot"] = "射擊", 268 | ["Bonus"] = "獎金", 269 | ["You lost!"] = "你輸了!", 270 | ["Dice"] = "骰子", 271 | ["Castle"] = "城堡", 272 | ["Back"] = "返回", 273 | ["Forgot password"] = "忘記密碼", 274 | ["Eyes"] = "眼睛", 275 | ["Claim"] = "索取", 276 | ["Frozen"] = "凍結", 277 | ["Gear"] = "檔", 278 | ["Victory"] = "勝利", 279 | ["Invalid CD Key."] = "無效的遊戲序號。", 280 | ["Tester"] = "測試儀", 281 | ["Feet"] = "雙腳", 282 | ["Paused"] = "暫停中", 283 | ["Design Director"] = "設計總監", 284 | ["Alien"] = "外星人", 285 | ["Last Name"] = "姓", 286 | ["First place"] = "第一名", 287 | ["Hearts"] = "心", 288 | ["Developed by"] = "游戲開發由", 289 | ["Machine Gun"] = "機關槍", 290 | ["Mission Objective"] = "任務目標", 291 | ["Assists"] = "協助", 292 | ["Purchase"] = "購買", 293 | ["Program Manager"] = "規劃經理", 294 | ["Senior"] = "高級", 295 | ["Thank you!"] = "謝謝!", 296 | ["Artists"] = "美術師", 297 | ["Interface Artist"] = "影片美術", 298 | ["Drop"] = "放下", 299 | ["Rocket Launcher"] = "火箭炮", 300 | ["Hammer"] = "鐵錘", 301 | ["Suspension"] = "懸挂", 302 | ["Lead"] = "領頭", 303 | ["Sniper"] = "狙擊手", 304 | ["Virtual Reality"] = "虛擬現實", 305 | ["VR comfort mode"] = "虛擬現實舒適模式", 306 | ["Yes"] = "是", 307 | ["Key"] = "關鍵", 308 | ["Shareware"] = "共享軟件", 309 | ["Medium"] = "中", 310 | ["Princess"] = "公主", 311 | ["Gauntlets"] = "鐵手套", 312 | ["Hard"] = "困難", 313 | ["Full"] = "完整版", 314 | ["Deaths"] = "死亡", 315 | ["Demo"] = "試玩版", 316 | ["Press any key to continue"] = "按下任意鍵以繼續", 317 | ["Visual Effects"] = "視覺效果", 318 | ["Goodbye!"] = "再見!", 319 | ["Drive"] = "駕駛", 320 | ["Very High"] = "最高", 321 | ["Animation Director"] = "動畫總監", 322 | ["Low"] = "低", 323 | ["Test Lead"] = "測試領導", 324 | ["High"] = "高", 325 | ["Widescreen"] = "寬螢幕", 326 | ["Third place"] = "第三名", 327 | ["V-sync"] = "垂直同步", 328 | ["Load Game"] = "載入游戲", 329 | ["Winner"] = "贏家", 330 | ["Foot"] = "腳", 331 | ["Quit"] = "退出", 332 | ["Volume"] = "音量", 333 | ["Demon"] = "魔鬼", 334 | ["Inventory"] = "裝備", 335 | ["Quality"] = "質量", 336 | ["Level"] = "級別", 337 | ["Music volume"] = "音樂音量", 338 | ["Multicore rendering"] = "多核心渲染", 339 | ["Graphics Options"] = "圖形設置", 340 | ["Weapon"] = "武器", 341 | ["Manuscript"] = "原稿", 342 | ["Capture"] = "捉取", 343 | ["Director"] = "導演", 344 | ["Gameplay Options"] = "游戲設置", 345 | ["Fullscreen"] = "全屏", 346 | ["Art Director"] = "美術總監", 347 | ["FOV"] = "視場角", 348 | ["Skeleton"] = "屍骨", 349 | ["First Person View"] = "第一人稱視角", 350 | ["Trilinear"] = "三線性", 351 | ["Down"] = "下", 352 | ["Filtering mode"] = "過濾模式", 353 | ["Cannot connect to server."] = "不能連接至服務器。", 354 | ["Encumbrance"] = "負擔", 355 | ["Advanced Graphics"] = "先進的圖形", 356 | ["Anisotropic"] = "異向", 357 | ["Difficulty Options"] = "難度設置", 358 | ["Use"] = "使用", 359 | ["Controls"] = "操作模式", 360 | ["Your team won!"] = "你的團隊勝利", 361 | ["Bloom"] = "盛開", 362 | ["Options"] = "設置", 363 | ["Username"] = "用戶名", 364 | ["Read"] = "讀", 365 | ["Instructions"] = "說明", 366 | ["Gamepad"] = "游戲手柄", 367 | ["Clone"] = "複製人", 368 | ["Mouse"] = "鼠標", 369 | ["First Name"] = "名字", 370 | ["Arrows"] = "箭", 371 | ["Space"] = "太空", 372 | ["Versus"] = "對抗模式", 373 | ["Jump"] = "跳", 374 | ["Tutorial"] = "教程", 375 | ["Cook"] = "煮", 376 | ["Deathmatch"] = "死亡競賽", 377 | ["Cooperative"] = "合作模式", 378 | ["Special thanks to"] = "特別感謝", 379 | ["Co-op"] = "團隊合作", 380 | ["Challenge mode"] = "挑戰模式", 381 | ["Password"] = "密碼", 382 | ["Hardcore game"] = "硬核游戲", 383 | ["English"] = "Traditional Chinese", 384 | ["Epic"] = "特級的", 385 | ["YES"] = "是", 386 | ["ltr"] = "ltr", 387 | ["Arm"] = "臂", 388 | ["World"] = "世界", 389 | ["Lock"] = "鎖", 390 | ["Voices"] = "聲音", 391 | ["Video"] = "視頻設置", 392 | ["Unlock"] = "開鎖", 393 | ["Sound"] = "聲音", 394 | ["Cancel"] = "取消", 395 | ["Match"] = "比賽", 396 | ["Tournament"] = "比賽", 397 | ["Skip"] = "跳過", 398 | ["Return to Main Menu?"] = "返回至主界面?", 399 | ["Replay"] = "重播", 400 | ["Impossible"] = "不可能", 401 | ["Quit?"] = "退出?", 402 | ["Press any key"] = "按下任意鍵", 403 | ["Replace"] = "更換", 404 | ["Are you sure you want to quit?"] = "你確定你需要退出嗎?", 405 | ["Texture detail"] = "材質細節", 406 | ["Medic"] = "軍醫", 407 | ["Free"] = "免費版", 408 | ["Price"] = "價錢", 409 | ["Double-click"] = "雙擊", 410 | ["Lite"] = "位版本", 411 | ["Hand"] = "手", 412 | ["Energy shields"] = "能量罩", 413 | ["Cheats detected!"] = "已偵測到作弊!", 414 | ["Error code:"] = "錯誤代碼:", 415 | ["Connection lost."] = "網絡連接失敗。", 416 | ["3D Modeling"] = "三維建模", 417 | ["Soundtrack"] = "原聲音樂", 418 | ["Coin"] = "硬幣", 419 | ["Background music"] = "背景音樂", 420 | ["You win!"] = "你贏了!", 421 | ["Speed"] = "速度", 422 | ["Climb"] = "爬上", 423 | ["Indie"] = "獨立製作", 424 | ["Quest"] = "追尋", 425 | ["No HMD detected"] = "未檢測到HMD", 426 | ["Camera"] = "攝影機", 427 | ["Prince"] = "王子", 428 | ["Goddess"] = "女神", 429 | ["Game design"] = "遊戲設計", 430 | ["Wizard"] = "巫師", 431 | ["Delete Character"] = "刪除角色", 432 | ["Button"] = "按鍵", 433 | ["Demonness"] = "女魔", 434 | ["The other player has disconnected."] = "另一個玩家斷線", 435 | ["Cinematics Director"] = "影片導演", 436 | ["Inverted"] = "反轉", 437 | ["All"] = "全部", 438 | ["Audio Director"] = "音樂總監", 439 | ["Code"] = "程序", 440 | ["Chapter"] = "章", 441 | ["Attack"] = "攻擊", 442 | ["Silver"] = "銀", 443 | ["Cinematic Animator"] = "影片動畫", 444 | ["Are you sure?"] = "你確定嗎?", 445 | ["Camera X-Axis"] = "攝影機X坐標軸", 446 | ["NO"] = "否", 447 | ["Staff"] = "杖", 448 | ["Go"] = "前往", 449 | ["Models"] = "模型", 450 | ["Inn"] = "客棧", 451 | ["Hair"] = "頭發", 452 | ["Death"] = "死亡", 453 | ["Keyboard"] = "鍵盤", 454 | ["Fly"] = "飛", 455 | ["Spaceship"] = "太空船", 456 | ["Cards"] = "卡片", 457 | ["Pick up"] = "拾起", 458 | ["Locked"] = "鎖定", 459 | ["Exit to Desktop?"] = "退出至桌面?", 460 | ["Gun"] = "槍", 461 | ["RPG"] = "RPG", 462 | ["Cast"] = "施咒語", 463 | ["Your opponent has disconnected."] = "你的對手斷線", 464 | ["Be careful!"] = "注意", 465 | ["Genre"] = "類型", 466 | ["Arms"] = "臂", 467 | ["Assist"] = "協助", 468 | ["Bronze"] = "青铜", 469 | ["Power-up"] = "提升功率", 470 | ["Mission"] = "任務", 471 | ["Item"] = "物品", 472 | ["Robot"] = "機器人", 473 | ["Ninja"] = "忍者", 474 | ["Inventory Full"] = "裝備已滿", 475 | ["Mage"] = "魔法師", 476 | ["Earth"] = "地球", 477 | ["The End"] = "結束", 478 | ["Assistant"] = "助理", 479 | ["Page"] = "頁", 480 | ["Left"] = "左", 481 | ["Sword"] = "劍", 482 | ["Shotgun"] = "散彈槍", 483 | ["Pirate"] = "海賊", 484 | ["Shooter game"] = "射擊游戲", 485 | ["Artificial Intelligence"] = "人工智能", 486 | ["Miss"] = "失誤", 487 | ["Puzzle game"] = "智力遊戲", 488 | ["Lives"] = "生命", 489 | ["Dagger"] = "短劍", 490 | ["Soldier"] = "戰士", 491 | ["Hit"] = "擊中 击中", 492 | ["Creative Director"] = "創意總監", 493 | ["Game"] = "游戲", 494 | ["Tournaments"] = "比賽", 495 | ["Armor"] = "護甲", 496 | ["Composer"] = "作曲家", 497 | ["Door"] = "門", 498 | ["Multiplayer"] = "聯機模式", 499 | ["Voice acting"] = "配音員", 500 | ["Craft"] = "技術", 501 | ["Discard"] = "拋棄", 502 | ["Gloves"] = "手套", 503 | ["Slowed"] = "減速", 504 | ["Sneak"] = "潛行", 505 | ["Experience points"] = "經驗值", 506 | ["Next track"] = "下一個曲目", 507 | ["Walk"] = "步行", 508 | ["Takeoff"] = "起飞 起飛", 509 | ["Chassis"] = "馬車", 510 | ["Gem"] = "寶石", 511 | ["Burning"] = "燃燒中", 512 | ["Wheels"] = "輪", 513 | ["Book"] = "書", 514 | ["Cyborg"] = "機器人", 515 | ["Sound engineer"] = "錄音師", 516 | ["Altitude"] = "高度", 517 | ["Gyroscope"] = "回轉儀", 518 | ["Magic"] = "魔法", 519 | ["Wand"] = "魔杖", 520 | ["Helmet"] = "鋼盔", 521 | ["Unhurt"] = "未受傷", 522 | ["Race"] = "競賽", 523 | ["Art gallery"] = "藝術館", 524 | ["No open games."] = "沒有招募中的游戲", 525 | ["Very Easy"] = "非常簡單", 526 | ["Technical artist"] = "技術設計", 527 | ["Open"] = "開", 528 | ["Throw"] = "扔", 529 | ["Character Designer"] = "角色設計", 530 | ["Time"] = "時間", 531 | ["The button"] = "按鍵", 532 | ["Cave"] = "洞穴", 533 | ["Spawn Point"] = "重生點", 534 | ["Love"] = "愛", 535 | ["Laps"] = "圈數", 536 | ["You cannot carry any more."] = "你拿不起了。", 537 | ["Rotate"] = "環繞", 538 | ["Resolution"] = "解析度", 539 | ["Lead programmer"] = "程序組長", 540 | ["You lose!"] = "你輸了!", 541 | ["Misc."] = "其他", 542 | ["Gods"] = "神", 543 | ["Enemy"] = "敵人", 544 | ["Beard"] = "胡子", 545 | ["Ingot"] = "金屬塊", 546 | ["Associate"] = "副", 547 | ["Graphics"] = "圖形設置", 548 | ["Extras"] = "演員", 549 | ["Singleplayer"] = "單人模式", 550 | ["No {0} detected"] = "未檢測到{0}", 551 | ["Medieval game"] = "中世紀式游戲", 552 | ["Bomb"] = "炸彈", 553 | ["Gold"] = "金", 554 | ["Thief"] = "盜賊", 555 | ["Nope"] = "不行", 556 | ["Buy"] = "購買", 557 | ["Bullet"] = "子彈", 558 | ["Bilinear"] = "雙線性", 559 | ["Gold medal"] = "金徽章", 560 | ["Respawning"] = "重生中", 561 | ["Retro game"] = "復古游戲", 562 | ["Weapons"] = "武器", 563 | ["Musician"] = "音樂家", 564 | ["Sound Effects"] = "音響效果", 565 | ["Defend"] = "防守", 566 | ["Junk"] = "沒用的", 567 | ["GAME OVER!"] = "游戲結束!", 568 | ["God"] = "神", 569 | ["Art"] = "美術", 570 | ["Reset save data?"] = "重設已保存數據", 571 | ["Rank"] = "軍階", 572 | ["Losses"] = "失敗", 573 | ["Dead"] = "死亡", 574 | ["Boots"] = "靴", 575 | ["Round"] = "回合", 576 | ["E-mail"] = "電子郵件", 577 | ["Male"] = "男性", 578 | ["Welcome"] = "歡迎", 579 | ["No"] = "否", 580 | ["The key"] = "關鍵", 581 | ["Your teammate has disconnected."] = "你的隊友斷線", 582 | ["You died."] = "你死了。", 583 | ["Board"] = "遊戲盤", 584 | ["Skin"] = "皮膚", 585 | ["Game development"] = "游戲開發", 586 | ["Transgender"] = "跨性別", 587 | ["Leaving tracking area"] = "無信號", 588 | ["Artist"] = "美術師", 589 | ["Score"] = "評分", 590 | ["Localization"] = "本土化", 591 | ["Objectives"] = "目標", 592 | ["Unconscious"] = "失去知覺", 593 | ["Zombie"] = "僵尸", 594 | ["Eye"] = "眼", 595 | ["Level designer"] = "關卡設計師", 596 | ["Men"] = "男人", 597 | ["OK"] = "OK", 598 | ["Jackpot"] = "頭獎", 599 | ["Right"] = "右", 600 | ["Chin"] = "下巴", 601 | ["Translated by the Polyglot Project"] = "翻譯由Polyglot Project 提供", 602 | ["Hands"] = "手", 603 | ["Rusty"] = "生銹的", 604 | ["Roleplaying game"] = "角色扮演游戲", 605 | ["Press Start to continue"] = "按下開始以繼續", 606 | ["Play again"] = "再玩一次", 607 | ["Racing"] = "競速遊戲", 608 | ["Loading..."] = "正在登錄中...", 609 | ["Drag"] = "拖", 610 | ["Respawn?"] = "重生?", 611 | ["Time left"] = "剩余時間", 612 | ["Video Quality"] = "視頻質量", 613 | ["Enemies"] = "敵人", 614 | ["Legs"] = "雙腿", 615 | ["Health"] = "健康值", 616 | ["Place"] = "名次", 617 | ["Up"] = "上", 618 | ["Next"] = "下一個", 619 | ["Depth"] = "深度", 620 | } 621 | } 622 | -------------------------------------------------------------------------------- /locales/ko.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["ko"] = { 3 | ["Poisoned"] = "중독", 4 | ["Sound designer"] = "음향 디자이너", 5 | ["Deity"] = "신", 6 | ["Production"] = "제작", 7 | ["Leg"] = "다리", 8 | ["Pause"] = "일시 정지", 9 | ["Multiplier"] = "배수", 10 | ["Game designer"] = "게임 디자이너", 11 | ["Man"] = "남자", 12 | ["Insane"] = "매니악", 13 | ["An error has occured."] = "오류가 발생했습니다.", 14 | ["Gifts"] = "선물", 15 | ["Tilt"] = "기울이기", 16 | ["Dungeon"] = "던전", 17 | ["Game over!"] = "게임 오버!", 18 | ["Look"] = "보기", 19 | ["Turn-based strategy"] = "턴제 전략", 20 | ["Junior"] = "주니어", 21 | ["Programmer"] = "프로그래머", 22 | ["Display"] = "화면 설정", 23 | ["Fuel"] = "연료", 24 | ["Difficulty"] = "난이도", 25 | ["Big"] = "대", 26 | ["Full Speed"] = "최고 속도", 27 | ["Return to Main Menu"] = "메인 메뉴로 돌아가기", 28 | ["Remember?"] = "계정 정보 저장", 29 | ["Planet"] = "행성", 30 | ["Class"] = "직업", 31 | ["Splitscreen"] = "분할 화면", 32 | ["In-app purchase"] = "앱 내 구매", 33 | ["Save Game"] = "게임 저장", 34 | ["Shake"] = "흔들기", 35 | ["Sound Options"] = "소리 설정", 36 | ["Lap"] = "랩", 37 | ["Easy"] = "쉬움", 38 | ["Special thanks"] = "특별 감사", 39 | ["Adventure game"] = "어드벤처 게임", 40 | ["No games found."] = "저장된 게임이 없습니다.", 41 | ["Animation"] = "애니메이션", 42 | ["Escape"] = "탈출하기", 43 | ["You won!"] = "승리하였습니다!", 44 | ["Previous track"] = "이전 곡", 45 | ["Kills"] = "킬", 46 | ["Database Admin"] = "데이터베이스 관리자", 47 | ["Second place"] = "이등", 48 | ["Previous"] = "이전", 49 | ["Wins"] = "승리", 50 | ["More"] = "다른", 51 | ["Voice volume"] = "음성 음량", 52 | ["Warning"] = "경고", 53 | ["Monster"] = "괴물", 54 | ["FPS"] = "FPS", 55 | ["Close"] = "닫기", 56 | ["Wet"] = "젖음", 57 | ["Voice actor"] = "성우", 58 | ["Strategy game"] = "전략 게임", 59 | ["Script writer"] = "대본가", 60 | ["Video Options"] = "영상 설정", 61 | ["Exit"] = "나가기", 62 | ["Exit?"] = "나가겠습니까?", 63 | ["Head"] = "머리", 64 | ["Load"] = "불러오기", 65 | ["Heal"] = "치료", 66 | ["Dragons"] = "드래곤", 67 | ["Exit to Desktop"] = "바탕화면으로 나가기", 68 | ["Hit points"] = "체력", 69 | ["Age"] = "나이", 70 | ["Tactics"] = "작전", 71 | ["Game developer"] = "게임 개발자", 72 | ["Adventure"] = "모험", 73 | ["Nose"] = "코", 74 | ["Login"] = "로그인", 75 | ["Invalid name!"] = "이름이 잘못되었습니다.", 76 | ["You have been defeated."] = "패배하였습니다.", 77 | ["Local Multiplayer"] = "로컬 멀티플레이", 78 | ["Music"] = "음악", 79 | ["Kill"] = "킬", 80 | ["Landing"] = "착륙", 81 | ["Talk"] = "대화하기", 82 | ["Name"] = "이름", 83 | ["Training"] = "트레이닝", 84 | ["Programmers"] = "프로그래머", 85 | ["Respawn"] = "부활", 86 | ["Ghost"] = "유령", 87 | ["Network Options"] = "네트워크 설정", 88 | ["Click"] = "클릭", 89 | ["Finger"] = "터치 조작", 90 | ["Pistol"] = "권총", 91 | ["Quiz game"] = "퀴즈 게임", 92 | ["Gift"] = "선물", 93 | ["Effect detail"] = "효과 세부 묘사", 94 | ["Air"] = "공기", 95 | ["Hips"] = "엉덩이", 96 | ["New Game"] = "새 게임", 97 | ["Save file corrupted."] = "저장된 게임에 오류가 있습니다.", 98 | ["Programming"] = "프로그래밍", 99 | ["Play Online"] = "온라인으로 플레이", 100 | ["Writer"] = "대본가", 101 | ["Chief Technical Officer"] = "최고 기술 책임자", 102 | ["Mail"] = "메일", 103 | ["Skill"] = "기술", 104 | ["Share"] = "공유하기", 105 | ["Action game"] = "액션 게임", 106 | ["Spread"] = "손가락 펼치기", 107 | ["Defeat"] = "패배", 108 | ["Inventory Capacity"] = "인벤토리 용량", 109 | ["Windowed"] = "창 모드", 110 | ["Drag and drop"] = "끌어다 놓기", 111 | ["Mission Objectives"] = "임무의 목표", 112 | ["Please wait..."] = "잠시만 기다려 주세요", 113 | ["HMD orientation reset"] = "HMD 방향 재설정", 114 | ["Ammunition"] = "탄환", 115 | ["Wounded"] = "부상", 116 | ["Shield"] = "방패", 117 | ["Endurance"] = "지구력", 118 | ["Silver medal"] = "은메달", 119 | ["Play"] = "플레이", 120 | ["Huge"] = "특대", 121 | ["Wood"] = "목재", 122 | ["Size"] = "크기", 123 | ["Fire"] = "불", 124 | ["Dragon"] = "드래곤", 125 | ["Continue"] = "계속", 126 | ["Fur"] = "털", 127 | ["Wings"] = "날개", 128 | ["Thorax"] = "상반신", 129 | ["Mouth"] = "입", 130 | ["Fonts"] = "글꼴", 131 | ["Spell"] = "주문", 132 | ["Heart"] = "하트", 133 | ["Critical Hit"] = "일격", 134 | ["Ears"] = "귀", 135 | ["Are you really sure?"] = "정말로 확실합니까?", 136 | ["Max"] = "최대", 137 | ["Casual game"] = "캐주얼 게임", 138 | ["Bow"] = "활", 139 | ["Image"] = "이미지", 140 | ["Priest"] = "사제", 141 | ["Objective"] = "목표", 142 | ["Metal"] = "쇠", 143 | ["Shields"] = "방패", 144 | ["Recordist"] = "녹음", 145 | ["Rifle"] = "소총", 146 | ["Zombies"] = "좀비", 147 | ["Sniper rifle"] = "저격총", 148 | ["Neck"] = "목", 149 | ["Color"] = "색", 150 | ["You are dead."] = "사망하였습니다.", 151 | ["Brakes"] = "브레이크", 152 | ["Boost"] = "가속하기", 153 | ["Project Manager"] = "프로젝트 관리자", 154 | ["Return"] = "돌아가기", 155 | ["Main Menu"] = "메뉴", 156 | ["Shadow"] = "그림자", 157 | ["Steering"] = "핸들 반응", 158 | ["Spin"] = "회전시키기", 159 | ["Sprint"] = "달리기", 160 | ["Fantasy game"] = "판타지 게임", 161 | ["Card"] = "카드", 162 | ["Science fiction game"] = "SF 게임", 163 | ["Female"] = "여성", 164 | ["Small"] = "소", 165 | ["Your team lost!"] = "팀 패배", 166 | ["Bullets"] = "탄", 167 | ["Challenge"] = "도전", 168 | ["Swipe"] = "밀기", 169 | ["Help"] = "도움말", 170 | ["Handling"] = "핸들링", 171 | ["Level up!"] = "레벨 업!", 172 | ["Position"] = "순위", 173 | ["Water"] = "물", 174 | ["Medal"] = "메달", 175 | ["Foley artist"] = "효과음 아티스트", 176 | ["Level design"] = "레벨 디자인", 177 | ["Animator"] = "애니메이터", 178 | ["Half Speed"] = "중간 속도", 179 | ["Platformer game"] = "플랫폼 게임", 180 | ["Incomplete"] = "미완료", 181 | ["Energy shield"] = "에너지 방어막", 182 | ["Mix"] = "섞기", 183 | ["Trial"] = "기간 한정 시험판", 184 | ["Sports game"] = "스포츠 게임", 185 | ["Images"] = "이미지", 186 | ["Technical Director"] = "기술 감독", 187 | ["Continue?"] = "계속할까요?", 188 | ["Loser"] = "패자", 189 | ["Mouse sensitivity"] = "마우스 감도", 190 | ["Publisher"] = "배급", 191 | ["Sound effect volume"] = "효과음 음량", 192 | ["Bronze medal"] = "동메달", 193 | ["Ammo"] = "탄환", 194 | ["Camera Y-Axis"] = "카메라 세로축", 195 | ["Woman"] = "여자", 196 | ["Complete"] = "완성", 197 | ["Destroy"] = "파괴하기", 198 | ["Save"] = "저장", 199 | ["Run"] = "달리기", 200 | ["Language"] = "언어", 201 | ["Test Manager"] = "테스트 관리자", 202 | ["Warrior"] = "전사", 203 | ["Third Person View"] = "3인칭 시점", 204 | ["Steer"] = "조종하기", 205 | ["Tiny"] = "특소", 206 | ["Min"] = "최소", 207 | ["Real-time strategy"] = "실시간 전략", 208 | ["HUD"] = "HUD", 209 | ["Tower defence game"] = "타워 디펜스 게임", 210 | ["Scroll"] = "스크롤", 211 | ["Go to"] = "(으)로 가기", 212 | ["Dodge"] = "피하기", 213 | ["Chest"] = "가슴", 214 | ["Platinum"] = "백금", 215 | ["Save data"] = "저장된 데이터", 216 | ["Critical Miss"] = "일격 빗나감", 217 | ["Saving..."] = "저장하는 중", 218 | ["Women"] = "여자", 219 | ["Treasure"] = "보물", 220 | ["Tap"] = "터치하기", 221 | ["Dead zone"] = "데드존", 222 | ["Graphic designer"] = "그래픽 디자이너", 223 | ["Kill Assist"] = "킬 보조", 224 | ["Anti-aliasing"] = "안티에일리어싱", 225 | ["Font"] = "글꼴", 226 | ["Sell"] = "팔기", 227 | ["Die"] = "주사위", 228 | ["Model detail"] = "모델 세부 사항", 229 | ["Build"] = "짓기", 230 | ["Ear"] = "귀", 231 | ["Credits"] = "제작진", 232 | ["High score"] = "최고 점수", 233 | ["Very Hard"] = "매우 어려움", 234 | ["Confirm"] = "확인", 235 | ["Ultra"] = "매우 높음", 236 | ["Music Player"] = "음악 재생기", 237 | ["Concept artist"] = "컨셉트 아티스트", 238 | ["Stunned"] = "스턴", 239 | ["Crouch"] = "조용히 걷기", 240 | ["Producer"] = "제작자", 241 | ["Version"] = "버전", 242 | ["Simulation game"] = "시뮬레이션 게임", 243 | ["Pinch"] = "손가락 모으기", 244 | ["Collect"] = "모으기", 245 | ["Please be careful."] = "주의하여 주십시오.", 246 | ["New Character"] = "캐릭터 만들기", 247 | ["Premium"] = "프리미엄 버전", 248 | ["Translation"] = "번역", 249 | ["Critical"] = "치명상", 250 | ["Respawn in:"] = "부활 장소:", 251 | ["Damage"] = "대미지", 252 | ["Arrow"] = "화살", 253 | ["Download"] = "내려받기", 254 | ["Register"] = "회원 가입", 255 | ["Knife"] = "칼", 256 | ["Downloadable content"] = "다운로드 콘텐츠", 257 | ["Online Multiplayer"] = "온라인 멀티플레이", 258 | ["Normal"] = "보통", 259 | ["Run away"] = "도망치기", 260 | ["Story"] = "이야기", 261 | ["Shader detail"] = "셰이더 세부 사항", 262 | ["Bet"] = "베팅하기", 263 | ["Press Start"] = "‘시작’을 누르세요", 264 | ["Yeah"] = "응", 265 | ["DLC"] = "DLC", 266 | ["Shadows"] = "그림자", 267 | ["Shoot"] = "쏘기", 268 | ["Bonus"] = "보너스", 269 | ["You lost!"] = "패배하였습니다!", 270 | ["Dice"] = "주사위", 271 | ["Castle"] = "성", 272 | ["Back"] = "뒤로", 273 | ["Forgot password"] = "비밀번호를 잊으셨나요?", 274 | ["Eyes"] = "눈", 275 | ["Claim"] = "갖기", 276 | ["Frozen"] = "동결", 277 | ["Gear"] = "변속기", 278 | ["Victory"] = "우승", 279 | ["Invalid CD Key."] = "잘못된 CD키입니다.", 280 | ["Tester"] = "테스터", 281 | ["Feet"] = "발", 282 | ["Paused"] = "일시 정지됨", 283 | ["Design Director"] = "디자인 감독", 284 | ["Alien"] = "외계인", 285 | ["Last Name"] = "성", 286 | ["First place"] = "일등", 287 | ["Hearts"] = "하트", 288 | ["Developed by"] = "개발자", 289 | ["Machine Gun"] = "기관총", 290 | ["Mission Objective"] = "임무의 목표", 291 | ["Assists"] = "보조", 292 | ["Purchase"] = "구매하기", 293 | ["Program Manager"] = "프로그램 관리자", 294 | ["Senior"] = "시니어", 295 | ["Thank you!"] = "감사합니다!", 296 | ["Artists"] = "아티스트", 297 | ["Interface Artist"] = "인터페이스 아티스트", 298 | ["Drop"] = "버리기", 299 | ["Rocket Launcher"] = "로켓 런처", 300 | ["Hammer"] = "철퇴", 301 | ["Suspension"] = "현가장치", 302 | ["Lead"] = "총책임자", 303 | ["Sniper"] = "저격수", 304 | ["Virtual Reality"] = "가상현실", 305 | ["VR comfort mode"] = "VR 효과 줄이기", 306 | ["Yes"] = "예", 307 | ["Key"] = "글쇠", 308 | ["Shareware"] = "셰어웨어", 309 | ["Medium"] = "중간", 310 | ["Princess"] = "공주", 311 | ["Gauntlets"] = "건틀릿", 312 | ["Hard"] = "어려움", 313 | ["Full"] = "풀 버전", 314 | ["Deaths"] = "사망", 315 | ["Demo"] = "체험판", 316 | ["Press any key to continue"] = "계속하려면 아무 키나 누르세요", 317 | ["Visual Effects"] = "시각 효과", 318 | ["Goodbye!"] = "안녕히 가세요!", 319 | ["Drive"] = "운전하기", 320 | ["Very High"] = "매우 높음", 321 | ["Animation Director"] = "애니메이션 감독", 322 | ["Low"] = "낮음", 323 | ["Test Lead"] = "테스트 관리 총지휘", 324 | ["High"] = "높음", 325 | ["Widescreen"] = "와이드스크린", 326 | ["Third place"] = "삼등", 327 | ["V-sync"] = "수직 동기", 328 | ["Load Game"] = "게임 불러오기", 329 | ["Winner"] = "승자", 330 | ["Foot"] = "발", 331 | ["Quit"] = "종료", 332 | ["Volume"] = "음량", 333 | ["Demon"] = "악마", 334 | ["Inventory"] = "인벤토리", 335 | ["Quality"] = "품질", 336 | ["Level"] = "레벨", 337 | ["Music volume"] = "음악 음량", 338 | ["Multicore rendering"] = "다중 코어 렌더링", 339 | ["Graphics Options"] = "그래픽 설정", 340 | ["Weapon"] = "무기", 341 | ["Manuscript"] = "대본", 342 | ["Capture"] = "확보", 343 | ["Director"] = "감독", 344 | ["Gameplay Options"] = "게임플레이 설정", 345 | ["Fullscreen"] = "전체화면", 346 | ["Art Director"] = "아트 감독", 347 | ["FOV"] = "시야각", 348 | ["Skeleton"] = "스켈레톤", 349 | ["First Person View"] = "1인칭 시점", 350 | ["Trilinear"] = "삼선형", 351 | ["Down"] = "아래", 352 | ["Filtering mode"] = "필터링 모드", 353 | ["Cannot connect to server."] = "서버에 연결할 수 없습니다.", 354 | ["Encumbrance"] = "인벤토리 무게", 355 | ["Advanced Graphics"] = "고급 그래픽 설정", 356 | ["Anisotropic"] = "비등방성", 357 | ["Difficulty Options"] = "난이도 설정", 358 | ["Use"] = "사용하기", 359 | ["Controls"] = "조작 방식", 360 | ["Your team won!"] = "팀 승리", 361 | ["Bloom"] = "블룸 효과", 362 | ["Options"] = "설정", 363 | ["Username"] = "아이디", 364 | ["Read"] = "읽기", 365 | ["Instructions"] = "설명", 366 | ["Gamepad"] = "게임 패드", 367 | ["Clone"] = "복제 인간", 368 | ["Mouse"] = "마우스", 369 | ["First Name"] = "이름", 370 | ["Arrows"] = "화살", 371 | ["Space"] = "우주", 372 | ["Versus"] = "대전 모드", 373 | ["Jump"] = "점프", 374 | ["Tutorial"] = "튜토리얼", 375 | ["Cook"] = "요리하기", 376 | ["Deathmatch"] = "데스매치", 377 | ["Cooperative"] = "협동 플레이", 378 | ["Special thanks to"] = "특별 감사:", 379 | ["Co-op"] = "협동", 380 | ["Challenge mode"] = "도전 모드", 381 | ["Password"] = "비밀번호", 382 | ["Hardcore game"] = "하드코어 게임", 383 | ["English"] = "Korean", 384 | ["Epic"] = "뛰어난", 385 | ["YES"] = "예", 386 | ["ltr"] = "ltr", 387 | ["Arm"] = "팔", 388 | ["World"] = "세계", 389 | ["Lock"] = "자물쇠", 390 | ["Voices"] = "음성", 391 | ["Video"] = "영상", 392 | ["Unlock"] = "잠김 해제", 393 | ["Sound"] = "음향", 394 | ["Cancel"] = "취소", 395 | ["Match"] = "대전", 396 | ["Tournament"] = "토너먼트", 397 | ["Skip"] = "건너뛰기", 398 | ["Return to Main Menu?"] = "메인 메뉴로 돌아갈까요?", 399 | ["Replay"] = "리플레이", 400 | ["Impossible"] = "불가능", 401 | ["Quit?"] = "종료할까요?", 402 | ["Press any key"] = "아무 키나 누르세요", 403 | ["Replace"] = "대치하기", 404 | ["Are you sure you want to quit?"] = "정말로 종료할까요?", 405 | ["Texture detail"] = "텍스처 세부 사항", 406 | ["Medic"] = "의무관", 407 | ["Free"] = "무료 버전 (부분 유료)", 408 | ["Price"] = "가격", 409 | ["Double-click"] = "이중 클릭", 410 | ["Lite"] = "라이트 버전", 411 | ["Hand"] = "손", 412 | ["Energy shields"] = "에너지 방어막", 413 | ["Cheats detected!"] = "치트 발견!", 414 | ["Error code:"] = "오류 코드:", 415 | ["Connection lost."] = "연결이 끊어졌습니다.", 416 | ["3D Modeling"] = "3D 모델링", 417 | ["Soundtrack"] = "사운드트랙", 418 | ["Coin"] = "동전", 419 | ["Background music"] = "배경 음악", 420 | ["You win!"] = "승리하였습니다!", 421 | ["Speed"] = "속도", 422 | ["Climb"] = "오르기", 423 | ["Indie"] = "인디", 424 | ["Quest"] = "퀘스트", 425 | ["No HMD detected"] = "HMD를 찾을 수 없습니다.", 426 | ["Camera"] = "카메라", 427 | ["Prince"] = "왕자", 428 | ["Goddess"] = "여신", 429 | ["Game design"] = "게임 디자인", 430 | ["Wizard"] = "마법사", 431 | ["Delete Character"] = "캐릭터 지우기", 432 | ["Button"] = "버튼", 433 | ["Demonness"] = "악마", 434 | ["The other player has disconnected."] = "다른 플레이어가 연결을 끊었습니다.", 435 | ["Cinematics Director"] = "영상 감독", 436 | ["Inverted"] = "반전", 437 | ["All"] = "모두", 438 | ["Audio Director"] = "오디오 감독", 439 | ["Code"] = "코드", 440 | ["Chapter"] = "챕터", 441 | ["Attack"] = "공격", 442 | ["Silver"] = "은", 443 | ["Cinematic Animator"] = "영상 애니메이터", 444 | ["Are you sure?"] = "확실합니까?", 445 | ["Camera X-Axis"] = "카메라 가로축", 446 | ["NO"] = "아니요", 447 | ["Staff"] = "봉", 448 | ["Go"] = "가기", 449 | ["Models"] = "모델", 450 | ["Inn"] = "여관", 451 | ["Hair"] = "머리카락", 452 | ["Death"] = "사망", 453 | ["Keyboard"] = "자판", 454 | ["Fly"] = "비행하기", 455 | ["Spaceship"] = "우주선", 456 | ["Cards"] = "카드", 457 | ["Pick up"] = "줍기", 458 | ["Locked"] = "잠김", 459 | ["Exit to Desktop?"] = "바탕화면으로 나가겠습니까?", 460 | ["Gun"] = "총", 461 | ["RPG"] = "RPG", 462 | ["Cast"] = "사용하기", 463 | ["Your opponent has disconnected."] = "상대가 연결을 끊었습니다.", 464 | ["Be careful!"] = "주의하십시오.", 465 | ["Genre"] = "장르", 466 | ["Arms"] = "팔", 467 | ["Assist"] = "보조", 468 | ["Bronze"] = "동", 469 | ["Power-up"] = "파워 업", 470 | ["Mission"] = "임무", 471 | ["Item"] = "아이템", 472 | ["Robot"] = "로봇", 473 | ["Ninja"] = "닌자", 474 | ["Inventory Full"] = "인벤토리 꽉 참", 475 | ["Mage"] = "마법사", 476 | ["Earth"] = "지구", 477 | ["The End"] = "끝", 478 | ["Assistant"] = "보조", 479 | ["Page"] = "페이지", 480 | ["Left"] = "왼쪽", 481 | ["Sword"] = "검", 482 | ["Shotgun"] = "산탄총", 483 | ["Pirate"] = "해적", 484 | ["Shooter game"] = "슈팅 게임", 485 | ["Artificial Intelligence"] = "인공지능", 486 | ["Miss"] = "빗나감", 487 | ["Puzzle game"] = "퍼즐 게임", 488 | ["Lives"] = "라이프", 489 | ["Dagger"] = "단검", 490 | ["Soldier"] = "군인", 491 | ["Hit"] = "타격", 492 | ["Creative Director"] = "크리에이티브 감독", 493 | ["Game"] = "게임", 494 | ["Tournaments"] = "토너먼트", 495 | ["Armor"] = "갑옷", 496 | ["Composer"] = "작곡", 497 | ["Door"] = "문", 498 | ["Multiplayer"] = "멀티플레이", 499 | ["Voice acting"] = "성우", 500 | ["Craft"] = "만들기", 501 | ["Discard"] = "포기하기", 502 | ["Gloves"] = "장갑", 503 | ["Slowed"] = "감속", 504 | ["Sneak"] = "몰래 가기", 505 | ["Experience points"] = "경험치", 506 | ["Next track"] = "다음 곡", 507 | ["Walk"] = "걷기", 508 | ["Takeoff"] = "이륙하기", 509 | ["Chassis"] = "섀시", 510 | ["Gem"] = "보석", 511 | ["Burning"] = "화상", 512 | ["Wheels"] = "바퀴", 513 | ["Book"] = "책", 514 | ["Cyborg"] = "사이보그", 515 | ["Sound engineer"] = "음향 엔지니어", 516 | ["Altitude"] = "고도", 517 | ["Gyroscope"] = "자이로스코프", 518 | ["Magic"] = "마법", 519 | ["Wand"] = "마법 지팡이", 520 | ["Helmet"] = "투구", 521 | ["Unhurt"] = "정상", 522 | ["Race"] = "경주하기", 523 | ["Art gallery"] = "아트 갤러리", 524 | ["No open games."] = "현재 열린 방이 없습니다.", 525 | ["Very Easy"] = "매우 쉬움", 526 | ["Technical artist"] = "테크니컬 아티스트", 527 | ["Open"] = "열기", 528 | ["Throw"] = "던지기", 529 | ["Character Designer"] = "캐릭터 디자이너", 530 | ["Time"] = "시간", 531 | ["The button"] = "버튼", 532 | ["Cave"] = "동굴", 533 | ["Spawn Point"] = "스폰 지점", 534 | ["Love"] = "사랑", 535 | ["Laps"] = "랩", 536 | ["You cannot carry any more."] = "더 지닐 수 없습니다.", 537 | ["Rotate"] = "돌리기", 538 | ["Resolution"] = "해상도", 539 | ["Lead programmer"] = "리드 프로그래머", 540 | ["You lose!"] = "패배하였습니다!", 541 | ["Misc."] = "기타", 542 | ["Gods"] = "신", 543 | ["Enemy"] = "적", 544 | ["Beard"] = "수염", 545 | ["Ingot"] = "주괴", 546 | ["Associate"] = "협력", 547 | ["Graphics"] = "그래픽", 548 | ["Extras"] = "추가 컨텐츠", 549 | ["Singleplayer"] = "싱글플레이", 550 | ["No {0} detected"] = "{0}을(를) 찾을 수 없습니다.", 551 | ["Medieval game"] = "중세 게임", 552 | ["Bomb"] = "폭탄", 553 | ["Gold"] = "금", 554 | ["Thief"] = "도둑", 555 | ["Nope"] = "아니", 556 | ["Buy"] = "사기", 557 | ["Bullet"] = "탄", 558 | ["Bilinear"] = "쌍선형", 559 | ["Gold medal"] = "금메달", 560 | ["Respawning"] = "부활하는 중", 561 | ["Retro game"] = "레트로 게임", 562 | ["Weapons"] = "무기", 563 | ["Musician"] = "연주", 564 | ["Sound Effects"] = "음향 효과", 565 | ["Defend"] = "방어하기", 566 | ["Junk"] = "저질", 567 | ["GAME OVER!"] = "게임 오버", 568 | ["God"] = "신", 569 | ["Art"] = "아트", 570 | ["Reset save data?"] = "저장된 데이터를 초기화할까요?", 571 | ["Rank"] = "계급", 572 | ["Losses"] = "패배", 573 | ["Dead"] = "사망", 574 | ["Boots"] = "신발", 575 | ["Round"] = "횟수", 576 | ["E-mail"] = "이메일", 577 | ["Male"] = "남성", 578 | ["Welcome"] = "환영합니다", 579 | ["No"] = "아니요", 580 | ["The key"] = "글쇠", 581 | ["Your teammate has disconnected."] = "팀원이 연결을 끊었습니다.", 582 | ["You died."] = "사망하였습니다.", 583 | ["Board"] = "판", 584 | ["Skin"] = "피부", 585 | ["Game development"] = "게임 개발", 586 | ["Transgender"] = "성전환자", 587 | ["Leaving tracking area"] = "인식 범위 밖입니다.", 588 | ["Artist"] = "아티스트", 589 | ["Score"] = "점수", 590 | ["Localization"] = "지역화", 591 | ["Objectives"] = "목표", 592 | ["Unconscious"] = "기절", 593 | ["Zombie"] = "좀비", 594 | ["Eye"] = "눈", 595 | ["Level designer"] = "레벨 디자이너", 596 | ["Men"] = "남자", 597 | ["OK"] = "확인", 598 | ["Jackpot"] = "잭팟", 599 | ["Right"] = "오른쪽", 600 | ["Chin"] = "턱", 601 | ["Translated by the Polyglot Project"] = "번역 제공: Polyglot Project", 602 | ["Hands"] = "손", 603 | ["Rusty"] = "녹슨", 604 | ["Roleplaying game"] = "롤플레잉 게임", 605 | ["Press Start to continue"] = "계속하려면 ‘시작’을 누르세요", 606 | ["Play again"] = "다시 하기", 607 | ["Racing"] = "레이싱", 608 | ["Loading..."] = "불러오는 중", 609 | ["Drag"] = "끌기", 610 | ["Respawn?"] = "부활하시겠습니까?", 611 | ["Time left"] = "남은 시간", 612 | ["Video Quality"] = "영상 화질", 613 | ["Enemies"] = "적들", 614 | ["Legs"] = "다리", 615 | ["Health"] = "체력", 616 | ["Place"] = "등수", 617 | ["Up"] = "위", 618 | ["Next"] = "다음", 619 | ["Depth"] = "깊이", 620 | } 621 | } 622 | -------------------------------------------------------------------------------- /locales/ja.lua: -------------------------------------------------------------------------------- 1 | return { 2 | ["ja"] = { 3 | ["Poisoned"] = "毒", 4 | ["Sound designer"] = "サウンドデザイナー", 5 | ["Deity"] = "神", 6 | ["Production"] = "製作", 7 | ["Leg"] = "脚", 8 | ["Pause"] = "ポーズ", 9 | ["Multiplier"] = "倍", 10 | ["Game designer"] = "ゲームデザイナー", 11 | ["Man"] = "男", 12 | ["Insane"] = "マニアック", 13 | ["An error has occured."] = "エラーが発生しました。", 14 | ["Gifts"] = "ギフト", 15 | ["Tilt"] = "ティルト", 16 | ["Dungeon"] = "ダンジョン", 17 | ["Game over!"] = "ゲームオーバー!", 18 | ["Look"] = "見る", 19 | ["Turn-based strategy"] = "ターン制シミュレーション", 20 | ["Junior"] = "ジュニア", 21 | ["Programmer"] = "プログラマー", 22 | ["Display"] = "ディスプレイ", 23 | ["Fuel"] = "燃料", 24 | ["Difficulty"] = "難易度", 25 | ["Big"] = "大", 26 | ["Full Speed"] = "全速力", 27 | ["Return to Main Menu"] = "メインメニューに戻る", 28 | ["Remember?"] = "保存しますか?", 29 | ["Planet"] = "惑星", 30 | ["Class"] = "クラス", 31 | ["Splitscreen"] = "画面分割", 32 | ["In-app purchase"] = "アプリ内購入", 33 | ["Save Game"] = "ゲームデータをセーブ", 34 | ["Shake"] = "シェイク", 35 | ["Sound Options"] = "サウンド設定", 36 | ["Lap"] = "ラップ", 37 | ["Easy"] = "易しい", 38 | ["Special thanks"] = "謝辞", 39 | ["Adventure game"] = "アドベンチャーゲーム", 40 | ["No games found."] = "セーブデータが見つかりません。", 41 | ["Animation"] = "アニメーション", 42 | ["Escape"] = "逃走する", 43 | ["You won!"] = "勝利!", 44 | ["Previous track"] = "先の曲", 45 | ["Kills"] = "キル", 46 | ["Database Admin"] = "データベースアドミン", 47 | ["Second place"] = "二位", 48 | ["Previous"] = "前へ", 49 | ["Wins"] = "勝利", 50 | ["More"] = "詳細", 51 | ["Voice volume"] = "ボイス音量", 52 | ["Warning"] = "警告", 53 | ["Monster"] = "モンスター", 54 | ["FPS"] = "FPS", 55 | ["Close"] = "閉じる", 56 | ["Wet"] = "濡れている", 57 | ["Voice actor"] = "声優", 58 | ["Strategy game"] = "ストラテジーゲーム", 59 | ["Script writer"] = "脚本家", 60 | ["Video Options"] = "ビデオ設定", 61 | ["Exit"] = "終了する", 62 | ["Exit?"] = "終了しますか?", 63 | ["Head"] = "頭", 64 | ["Load"] = "ロード", 65 | ["Heal"] = "回復する", 66 | ["Dragons"] = "ドラゴン", 67 | ["Exit to Desktop"] = "終了してデスクトップへ戻る", 68 | ["Hit points"] = "ヒットポイント", 69 | ["Age"] = "年齢", 70 | ["Tactics"] = "作戦", 71 | ["Game developer"] = "ゲーム開発者", 72 | ["Adventure"] = "アドベンチャー", 73 | ["Nose"] = "鼻", 74 | ["Login"] = "ログイン", 75 | ["Invalid name!"] = "無効な名前です!", 76 | ["You have been defeated."] = "敗北しました。", 77 | ["Local Multiplayer"] = "ローカルマルチプレイ", 78 | ["Music"] = "音楽", 79 | ["Kill"] = "キル", 80 | ["Landing"] = "着陸する", 81 | ["Talk"] = "話す", 82 | ["Name"] = "名前", 83 | ["Training"] = "トレーニング", 84 | ["Programmers"] = "プログラマー", 85 | ["Respawn"] = "復活", 86 | ["Ghost"] = "幽霊", 87 | ["Network Options"] = "ネットワーク設定", 88 | ["Click"] = "クリック", 89 | ["Finger"] = "フィンガー", 90 | ["Pistol"] = "ピストル", 91 | ["Quiz game"] = "クイズゲーム", 92 | ["Gift"] = "ギフト", 93 | ["Effect detail"] = "エフェクト詳細設定", 94 | ["Air"] = "風", 95 | ["Hips"] = "腰", 96 | ["New Game"] = "新しいゲーム", 97 | ["Save file corrupted."] = "セーブデータが破損しています。", 98 | ["Programming"] = "プログラミング", 99 | ["Play Online"] = "オンラインでプレイ", 100 | ["Writer"] = "脚本家", 101 | ["Chief Technical Officer"] = "最高技術責任者", 102 | ["Mail"] = "メール", 103 | ["Skill"] = "スキル", 104 | ["Share"] = "共有", 105 | ["Action game"] = "アクションゲーム", 106 | ["Spread"] = "スプレッド", 107 | ["Defeat"] = "敗北", 108 | ["Inventory Capacity"] = "インベントリ容量", 109 | ["Windowed"] = "ウィンドウモード", 110 | ["Drag and drop"] = "ドラッグ・アンド・ドロップ", 111 | ["Mission Objectives"] = "ミッション目標", 112 | ["Please wait..."] = "お待ちください…", 113 | ["HMD orientation reset"] = "HMDの画面位置設定をリセット", 114 | ["Ammunition"] = "弾薬", 115 | ["Wounded"] = "負傷", 116 | ["Shield"] = "盾", 117 | ["Endurance"] = "生命力", 118 | ["Silver medal"] = "シルバーメダル", 119 | ["Play"] = "プレイ", 120 | ["Huge"] = "巨大", 121 | ["Wood"] = "木", 122 | ["Size"] = "サイズ", 123 | ["Fire"] = "火", 124 | ["Dragon"] = "ドラゴン", 125 | ["Continue"] = "続ける", 126 | ["Fur"] = "毛皮", 127 | ["Wings"] = "ウィング", 128 | ["Thorax"] = "胸郭", 129 | ["Mouth"] = "口", 130 | ["Fonts"] = "フォント", 131 | ["Spell"] = "呪文", 132 | ["Heart"] = "ハート", 133 | ["Critical Hit"] = "クリティカルヒット", 134 | ["Ears"] = "耳", 135 | ["Are you really sure?"] = "本当によろしいですか?", 136 | ["Max"] = "最大", 137 | ["Casual game"] = "カジュアルゲーム", 138 | ["Bow"] = "弓", 139 | ["Image"] = "画像", 140 | ["Priest"] = "僧侶", 141 | ["Objective"] = "目標", 142 | ["Metal"] = "金", 143 | ["Shields"] = "盾", 144 | ["Recordist"] = "録音", 145 | ["Rifle"] = "ライフル", 146 | ["Zombies"] = "ゾンビ", 147 | ["Sniper rifle"] = "スナイパーライフル", 148 | ["Neck"] = "首", 149 | ["Color"] = "色", 150 | ["You are dead."] = "死にました。", 151 | ["Brakes"] = "ブレーキ", 152 | ["Boost"] = "ブーストする", 153 | ["Project Manager"] = "企画担当", 154 | ["Return"] = "戻る", 155 | ["Main Menu"] = "メインメニュー", 156 | ["Shadow"] = "シャドウ", 157 | ["Steering"] = "ステアリング", 158 | ["Spin"] = "回転させる", 159 | ["Sprint"] = "走る", 160 | ["Fantasy game"] = "ファンタジーゲーム", 161 | ["Card"] = "カード", 162 | ["Science fiction game"] = "SFゲーム", 163 | ["Female"] = "女", 164 | ["Small"] = "小", 165 | ["Your team lost!"] = "チームの敗北!", 166 | ["Bullets"] = "弾", 167 | ["Challenge"] = "チャレンジ", 168 | ["Swipe"] = "スワイプ", 169 | ["Help"] = "ヘルプ", 170 | ["Handling"] = "ハンドリング", 171 | ["Level up!"] = "レベルアップ!", 172 | ["Position"] = "ポジション", 173 | ["Water"] = "水", 174 | ["Medal"] = "メダル", 175 | ["Foley artist"] = "フォーリーアーティスト", 176 | ["Level design"] = "レベルデザイン", 177 | ["Animator"] = "アニメーター", 178 | ["Half Speed"] = "半速力", 179 | ["Platformer game"] = "プラットフォームゲーム", 180 | ["Incomplete"] = "未完了", 181 | ["Energy shield"] = "エネルギーシールド", 182 | ["Mix"] = "調合", 183 | ["Trial"] = "体験版", 184 | ["Sports game"] = "スポーツゲーム", 185 | ["Images"] = "画像", 186 | ["Technical Director"] = "技術監督", 187 | ["Continue?"] = "続けますか?", 188 | ["Loser"] = "敗者", 189 | ["Mouse sensitivity"] = "マウス感度", 190 | ["Publisher"] = "著作", 191 | ["Sound effect volume"] = "SE音量", 192 | ["Bronze medal"] = "ブロンズメダル", 193 | ["Ammo"] = "弾薬", 194 | ["Camera Y-Axis"] = "カメラ操作:上下", 195 | ["Woman"] = "女", 196 | ["Complete"] = "完了済", 197 | ["Destroy"] = "破壊する", 198 | ["Save"] = "セーブ", 199 | ["Run"] = "走る", 200 | ["Language"] = "言語", 201 | ["Test Manager"] = "テスト管理者", 202 | ["Warrior"] = "戦士", 203 | ["Third Person View"] = "三人称視点", 204 | ["Steer"] = "操舵する", 205 | ["Tiny"] = "極小", 206 | ["Min"] = "最低", 207 | ["Real-time strategy"] = "リアルタイムシミュレーション", 208 | ["HUD"] = "HUD", 209 | ["Tower defence game"] = "タワーディフェンスゲーム", 210 | ["Scroll"] = "スクロール", 211 | ["Go to"] = "へ移動する", 212 | ["Dodge"] = "避ける", 213 | ["Chest"] = "胸", 214 | ["Platinum"] = "白金", 215 | ["Save data"] = "セーブデータ", 216 | ["Critical Miss"] = "クリティカルミス", 217 | ["Saving..."] = "セーブ中…", 218 | ["Women"] = "女", 219 | ["Treasure"] = "財宝", 220 | ["Tap"] = "タップ", 221 | ["Dead zone"] = "デッドゾーン", 222 | ["Graphic designer"] = "グラフィックデザイナー", 223 | ["Kill Assist"] = "キルアシスト", 224 | ["Anti-aliasing"] = "アンチエイリアス", 225 | ["Font"] = "フォント", 226 | ["Sell"] = "売る", 227 | ["Die"] = "サイコロ", 228 | ["Model detail"] = "モデルの詳細", 229 | ["Build"] = "建築", 230 | ["Ear"] = "耳", 231 | ["Credits"] = "クレジット", 232 | ["High score"] = "ハイスコア", 233 | ["Very Hard"] = "とても難しい", 234 | ["Confirm"] = "決定", 235 | ["Ultra"] = "ウルトラ", 236 | ["Music Player"] = "音楽プレーヤー", 237 | ["Concept artist"] = "コンセプトアーティスト", 238 | ["Stunned"] = "スタン", 239 | ["Crouch"] = "しゃがむ", 240 | ["Producer"] = "プロデューサー", 241 | ["Version"] = "バージョン", 242 | ["Simulation game"] = "シミュレーションゲーム", 243 | ["Pinch"] = "ピンチ", 244 | ["Collect"] = "集める", 245 | ["Please be careful."] = "気をつけてください。", 246 | ["New Character"] = "新規キャラクター", 247 | ["Premium"] = "プレミアム", 248 | ["Translation"] = "翻訳", 249 | ["Critical"] = "瀕死", 250 | ["Respawn in:"] = "復活まで:", 251 | ["Damage"] = "ダメージ", 252 | ["Arrow"] = "矢", 253 | ["Download"] = "ダウンロード", 254 | ["Register"] = "登録", 255 | ["Knife"] = "ナイフ", 256 | ["Downloadable content"] = "ダウンロードコンテンツ", 257 | ["Online Multiplayer"] = "オンラインマルチプレイ", 258 | ["Normal"] = "通常", 259 | ["Run away"] = "逃げる", 260 | ["Story"] = "ストーリー", 261 | ["Shader detail"] = "シェーダーの詳細", 262 | ["Bet"] = "ベット", 263 | ["Press Start"] = "STARTボタンを押す", 264 | ["Yeah"] = "いいよ", 265 | ["DLC"] = "DLC", 266 | ["Shadows"] = "シャドウ", 267 | ["Shoot"] = "撃つ", 268 | ["Bonus"] = "ボーナス", 269 | ["You lost!"] = "敗北!", 270 | ["Dice"] = "サイコロ", 271 | ["Castle"] = "城", 272 | ["Back"] = "戻る", 273 | ["Forgot password"] = "パスワードを忘れた", 274 | ["Eyes"] = "目", 275 | ["Claim"] = "入手する", 276 | ["Frozen"] = "凍結", 277 | ["Gear"] = "ギア", 278 | ["Victory"] = "勝利", 279 | ["Invalid CD Key."] = "無効なCDキーです。", 280 | ["Tester"] = "テスター", 281 | ["Feet"] = "足", 282 | ["Paused"] = "ポーズ中", 283 | ["Design Director"] = "デザイン監督", 284 | ["Alien"] = "エイリアン", 285 | ["Last Name"] = "苗字", 286 | ["First place"] = "一位", 287 | ["Hearts"] = "ハート", 288 | ["Developed by"] = "開発", 289 | ["Machine Gun"] = "マシンガン", 290 | ["Mission Objective"] = "ミッション目標", 291 | ["Assists"] = "アシスト", 292 | ["Purchase"] = "購入", 293 | ["Program Manager"] = "番組担当", 294 | ["Senior"] = "シニア", 295 | ["Thank you!"] = "ありがとう!", 296 | ["Artists"] = "アーティスト", 297 | ["Interface Artist"] = "インターフェイスアーティスト", 298 | ["Drop"] = "捨てる", 299 | ["Rocket Launcher"] = "ロケットランチャー", 300 | ["Hammer"] = "戦鎚", 301 | ["Suspension"] = "サスペンション", 302 | ["Lead"] = "リード", 303 | ["Sniper"] = "狙撃手", 304 | ["Virtual Reality"] = "バーチャルリアリティ", 305 | ["VR comfort mode"] = "VR向けモード", 306 | ["Yes"] = "はい", 307 | ["Key"] = "キー", 308 | ["Shareware"] = "シェアウェア", 309 | ["Medium"] = "中", 310 | ["Princess"] = "姫", 311 | ["Gauntlets"] = "籠手", 312 | ["Hard"] = "難しい", 313 | ["Full"] = "完全版", 314 | ["Deaths"] = "デス", 315 | ["Demo"] = "デモ", 316 | ["Press any key to continue"] = "続けるにはいずれかのキーを押す", 317 | ["Visual Effects"] = "特殊効果", 318 | ["Goodbye!"] = "さようなら!", 319 | ["Drive"] = "運転する", 320 | ["Very High"] = "最高", 321 | ["Animation Director"] = "アニメーション監督", 322 | ["Low"] = "低", 323 | ["Test Lead"] = "テスト管理総指揮", 324 | ["High"] = "高", 325 | ["Widescreen"] = "ワイドスクリーン", 326 | ["Third place"] = "三位", 327 | ["V-sync"] = "垂直同期", 328 | ["Load Game"] = "ゲームデータをロード", 329 | ["Winner"] = "勝者", 330 | ["Foot"] = "足", 331 | ["Quit"] = "終了する", 332 | ["Volume"] = "ボリューム", 333 | ["Demon"] = "悪魔", 334 | ["Inventory"] = "インベントリ", 335 | ["Quality"] = "クオリティ", 336 | ["Level"] = "ステージ", 337 | ["Music volume"] = "BGM音量", 338 | ["Multicore rendering"] = "マルチコアレンダリング", 339 | ["Graphics Options"] = "グラフィック設定", 340 | ["Weapon"] = "武器", 341 | ["Manuscript"] = "脚本", 342 | ["Capture"] = "確保する", 343 | ["Director"] = "監督", 344 | ["Gameplay Options"] = "ゲームプレイ設定", 345 | ["Fullscreen"] = "フルスクリーン", 346 | ["Art Director"] = "美術監督", 347 | ["FOV"] = "視野角", 348 | ["Skeleton"] = "スケルトン", 349 | ["First Person View"] = "一人称視点", 350 | ["Trilinear"] = "トライリニア", 351 | ["Down"] = "下", 352 | ["Filtering mode"] = "フィルタリング モード", 353 | ["Cannot connect to server."] = "サーバーに接続できません。", 354 | ["Encumbrance"] = "持ち運べる量", 355 | ["Advanced Graphics"] = "グラフィック詳細設定", 356 | ["Anisotropic"] = "異方性", 357 | ["Difficulty Options"] = "難易度設定", 358 | ["Use"] = "使用する", 359 | ["Controls"] = "操作方法", 360 | ["Your team won!"] = "チームの勝利!", 361 | ["Bloom"] = "ブルーム効果", 362 | ["Options"] = "設定", 363 | ["Username"] = "ユーザーネーム", 364 | ["Read"] = "読む", 365 | ["Instructions"] = "説明", 366 | ["Gamepad"] = "ゲームパッド", 367 | ["Clone"] = "クローン", 368 | ["Mouse"] = "マウス", 369 | ["First Name"] = "名前", 370 | ["Arrows"] = "矢", 371 | ["Space"] = "宇宙", 372 | ["Versus"] = "対戦", 373 | ["Jump"] = "ジャンプする", 374 | ["Tutorial"] = "チュートリアル", 375 | ["Cook"] = "調理", 376 | ["Deathmatch"] = "デスマッチ", 377 | ["Cooperative"] = "協力モード", 378 | ["Special thanks to"] = "謝辞", 379 | ["Co-op"] = "協力", 380 | ["Challenge mode"] = "チャレンジモード", 381 | ["Password"] = "パスワード", 382 | ["Hardcore game"] = "ハードコアゲーム", 383 | ["English"] = "Japanese", 384 | ["Epic"] = "壮麗な", 385 | ["YES"] = "はい", 386 | ["ltr"] = "ltr", 387 | ["Arm"] = "腕", 388 | ["World"] = "世界", 389 | ["Lock"] = "鍵", 390 | ["Voices"] = "ボイス", 391 | ["Video"] = "ビデオクオリティ", 392 | ["Unlock"] = "アンロック", 393 | ["Sound"] = "サウンド", 394 | ["Cancel"] = "キャンセル", 395 | ["Match"] = "マッチ", 396 | ["Tournament"] = "トーナメント", 397 | ["Skip"] = "スキップ", 398 | ["Return to Main Menu?"] = "メインメニューに戻りますか?", 399 | ["Replay"] = "リプレイ", 400 | ["Impossible"] = "クリア不可能", 401 | ["Quit?"] = "終了しますか?", 402 | ["Press any key"] = "いずれかのキーを押す", 403 | ["Replace"] = "入れ替え", 404 | ["Are you sure you want to quit?"] = "本当に終了しますか?", 405 | ["Texture detail"] = "テクスチャの詳細", 406 | ["Medic"] = "メディック", 407 | ["Free"] = "無料版", 408 | ["Price"] = "価格", 409 | ["Double-click"] = "ダブルクリック", 410 | ["Lite"] = "Lite版", 411 | ["Hand"] = "手", 412 | ["Energy shields"] = "エネルギーシールド", 413 | ["Cheats detected!"] = "チート検出!", 414 | ["Error code:"] = "エラーコード:", 415 | ["Connection lost."] = "接続が切断されました。", 416 | ["3D Modeling"] = "3Dモデリング", 417 | ["Soundtrack"] = "サウンドトラック", 418 | ["Coin"] = "硬貨", 419 | ["Background music"] = "BGM", 420 | ["You win!"] = "勝利!", 421 | ["Speed"] = "速度", 422 | ["Climb"] = "登る", 423 | ["Indie"] = "独立系開発会社", 424 | ["Quest"] = "クエスト", 425 | ["No HMD detected"] = "HMDが接続されていません", 426 | ["Camera"] = "カメラ", 427 | ["Prince"] = "王子", 428 | ["Goddess"] = "女神", 429 | ["Game design"] = "ゲームデザイン", 430 | ["Wizard"] = "魔術師", 431 | ["Delete Character"] = "キャラクター削除", 432 | ["Button"] = "ボタン", 433 | ["Demonness"] = "女悪魔", 434 | ["The other player has disconnected."] = "他のプレイヤーが接続を切断しました。", 435 | ["Cinematics Director"] = "シネマティックディレクター", 436 | ["Inverted"] = "反転", 437 | ["All"] = "すべて", 438 | ["Audio Director"] = "音響監督", 439 | ["Code"] = "コード", 440 | ["Chapter"] = "チャプター", 441 | ["Attack"] = "攻める", 442 | ["Silver"] = "銀", 443 | ["Cinematic Animator"] = "シネマティックアニメーター", 444 | ["Are you sure?"] = "よろしいですか?", 445 | ["Camera X-Axis"] = "カメラ操作:左右", 446 | ["NO"] = "いいえ", 447 | ["Staff"] = "杖", 448 | ["Go"] = "移動する", 449 | ["Models"] = "モデル", 450 | ["Inn"] = "宿", 451 | ["Hair"] = "髪", 452 | ["Death"] = "デス", 453 | ["Keyboard"] = "キーボード", 454 | ["Fly"] = "飛ぶ", 455 | ["Spaceship"] = "宇宙船", 456 | ["Cards"] = "カード", 457 | ["Pick up"] = "拾う", 458 | ["Locked"] = "ロック中", 459 | ["Exit to Desktop?"] = "終了してデスクトップへ戻りますか?", 460 | ["Gun"] = "銃", 461 | ["RPG"] = "RPG", 462 | ["Cast"] = "詠唱する", 463 | ["Your opponent has disconnected."] = "相手プレイヤーが接続を切断しました。", 464 | ["Be careful!"] = "気をつけて!", 465 | ["Genre"] = "ジャンル", 466 | ["Arms"] = "腕", 467 | ["Assist"] = "アシスト", 468 | ["Bronze"] = "銅", 469 | ["Power-up"] = "パワーアップ", 470 | ["Mission"] = "ミッション", 471 | ["Item"] = "アイテム", 472 | ["Robot"] = "ロボット", 473 | ["Ninja"] = "忍者", 474 | ["Inventory Full"] = "インベントリがいっぱいです", 475 | ["Mage"] = "魔法使い", 476 | ["Earth"] = "地球", 477 | ["The End"] = "終わり", 478 | ["Assistant"] = "アシスタント", 479 | ["Page"] = "ページ", 480 | ["Left"] = "左", 481 | ["Sword"] = "剣", 482 | ["Shotgun"] = "ショットガン", 483 | ["Pirate"] = "海賊", 484 | ["Shooter game"] = "シューティングゲーム", 485 | ["Artificial Intelligence"] = "人工知能", 486 | ["Miss"] = "ミス", 487 | ["Puzzle game"] = "パズルゲーム", 488 | ["Lives"] = "ライフ", 489 | ["Dagger"] = "短刀", 490 | ["Soldier"] = "ソルジャー", 491 | ["Hit"] = "ヒット", 492 | ["Creative Director"] = "クリエイティブディレクター", 493 | ["Game"] = "ゲーム", 494 | ["Tournaments"] = "トーナメント", 495 | ["Armor"] = "鎧", 496 | ["Composer"] = "編曲", 497 | ["Door"] = "扉", 498 | ["Multiplayer"] = "マルチプレイ", 499 | ["Voice acting"] = "声優", 500 | ["Craft"] = "作成", 501 | ["Discard"] = "捨てる", 502 | ["Gloves"] = "手袋", 503 | ["Slowed"] = "減速", 504 | ["Sneak"] = "忍ぶ", 505 | ["Experience points"] = "経験値", 506 | ["Next track"] = "次の曲", 507 | ["Walk"] = "歩く", 508 | ["Takeoff"] = "離陸する", 509 | ["Chassis"] = "シャシ", 510 | ["Gem"] = "ジェム", 511 | ["Burning"] = "炎上", 512 | ["Wheels"] = "乗り物", 513 | ["Book"] = "本", 514 | ["Cyborg"] = "サイボーグ", 515 | ["Sound engineer"] = "サウンドエンジニア", 516 | ["Altitude"] = "高度", 517 | ["Gyroscope"] = "ジャイロ", 518 | ["Magic"] = "魔法", 519 | ["Wand"] = "魔法の杖", 520 | ["Helmet"] = "兜", 521 | ["Unhurt"] = "無傷", 522 | ["Race"] = "競争する", 523 | ["Art gallery"] = "アートギャラリー", 524 | ["No open games."] = "参加可能なゲームがありません。", 525 | ["Very Easy"] = "とても易しい", 526 | ["Technical artist"] = "テクニカルアーティスト", 527 | ["Open"] = "開く", 528 | ["Throw"] = "投げる", 529 | ["Character Designer"] = "キャラクターデザイナー", 530 | ["Time"] = "タイム", 531 | ["The button"] = "ボタン", 532 | ["Cave"] = "洞窟", 533 | ["Spawn Point"] = "復活ポイント", 534 | ["Love"] = "愛", 535 | ["Laps"] = "ラップ", 536 | ["You cannot carry any more."] = "これ以上持てません。", 537 | ["Rotate"] = "回転", 538 | ["Resolution"] = "解像度", 539 | ["Lead programmer"] = "リードプログラマー", 540 | ["You lose!"] = "敗北!", 541 | ["Misc."] = "その他", 542 | ["Gods"] = "神々", 543 | ["Enemy"] = "敵", 544 | ["Beard"] = "髭", 545 | ["Ingot"] = "延べ棒", 546 | ["Associate"] = "協力", 547 | ["Graphics"] = "グラフィック", 548 | ["Extras"] = "エキストラ", 549 | ["Singleplayer"] = "シングルプレイ", 550 | ["No {0} detected"] = "{0} が接続されていません", 551 | ["Medieval game"] = "中世風ゲーム", 552 | ["Bomb"] = "爆弾", 553 | ["Gold"] = "金", 554 | ["Thief"] = "盗賊", 555 | ["Nope"] = "だめ", 556 | ["Buy"] = "買う", 557 | ["Bullet"] = "弾", 558 | ["Bilinear"] = "バイリニア", 559 | ["Gold medal"] = "ゴールドメダル", 560 | ["Respawning"] = "復活中", 561 | ["Retro game"] = "レトロゲーム", 562 | ["Weapons"] = "武器", 563 | ["Musician"] = "演奏", 564 | ["Sound Effects"] = "SE", 565 | ["Defend"] = "守る", 566 | ["Junk"] = "がらくたの", 567 | ["GAME OVER!"] = "ゲームオーバー!", 568 | ["God"] = "神", 569 | ["Art"] = "アート", 570 | ["Reset save data?"] = "セーブデータを消去しますか?", 571 | ["Rank"] = "ランク", 572 | ["Losses"] = "敗北", 573 | ["Dead"] = "死亡", 574 | ["Boots"] = "靴", 575 | ["Round"] = "ラウンド", 576 | ["E-mail"] = "Eメール", 577 | ["Male"] = "男", 578 | ["Welcome"] = "ようこそ", 579 | ["No"] = "いいえ", 580 | ["The key"] = "キー", 581 | ["Your teammate has disconnected."] = "味方プレイヤーが接続を切断しました。", 582 | ["You died."] = "死にました。", 583 | ["Board"] = "盤", 584 | ["Skin"] = "肌", 585 | ["Game development"] = "ゲーム開発", 586 | ["Transgender"] = "トランスジェンダー", 587 | ["Leaving tracking area"] = "通信圏外です", 588 | ["Artist"] = "アーティスト", 589 | ["Score"] = "スコア", 590 | ["Localization"] = "ローカリゼーション", 591 | ["Objectives"] = "目標", 592 | ["Unconscious"] = "気絶", 593 | ["Zombie"] = "ゾンビ", 594 | ["Eye"] = "目", 595 | ["Level designer"] = "レベルデザイナー", 596 | ["Men"] = "男", 597 | ["OK"] = "OK", 598 | ["Jackpot"] = "ジャックポット", 599 | ["Right"] = "右", 600 | ["Chin"] = "顎", 601 | ["Translated by the Polyglot Project"] = "翻訳提供:Polyglotプロジェクト", 602 | ["Hands"] = "手", 603 | ["Rusty"] = "錆びた", 604 | ["Roleplaying game"] = "ロールプレイングゲーム", 605 | ["Press Start to continue"] = "続けるにはSTARTボタンを押す", 606 | ["Play again"] = "再プレイ", 607 | ["Racing"] = "レース", 608 | ["Loading..."] = "ローディング中…", 609 | ["Drag"] = "ドラッグ", 610 | ["Respawn?"] = "復活しますか?", 611 | ["Time left"] = "残り時間", 612 | ["Video Quality"] = "ビデオクオリティ", 613 | ["Enemies"] = "敵", 614 | ["Legs"] = "脚", 615 | ["Health"] = "ヘルス", 616 | ["Place"] = "順位", 617 | ["Up"] = "上", 618 | ["Next"] = "次へ", 619 | ["Depth"] = "深度", 620 | } 621 | } 622 | --------------------------------------------------------------------------------