diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 4239fd7..f141647 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -20,7 +20,7 @@ func TestNew(t *testing.T) { assert.NotEmpty(t, cfg.Formats.JSON) assert.NotEmpty(t, cfg.Formats.PlainText) assert.True(t, len(cfg.Codes) >= 19) - assert.True(t, len(cfg.Templates) >= 2) + assert.True(t, len(cfg.Templates) >= 1) assert.NotEmpty(t, cfg.TemplateName) assert.True(t, cfg.Templates.Has(cfg.TemplateName)) assert.Equal(t, uint16(http.StatusNotFound), cfg.DefaultCodeToRender) diff --git a/internal/http/handlers/error_page/handler.go b/internal/http/handlers/error_page/handler.go index 418f7e5..6588e5c 100644 --- a/internal/http/handlers/error_page/handler.go +++ b/internal/http/handlers/error_page/handler.go @@ -13,7 +13,7 @@ import ( const contentTypeHeader = "Content-Type" // New creates a new handler that returns an error page with the specified status code and format. -func New(cfg *config.Config, log *logger.Logger) http.Handler { //nolint:funlen,gocognit +func New(cfg *config.Config, log *logger.Logger) http.Handler { //nolint:funlen,gocognit,gocyclo return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var code uint16 @@ -86,6 +86,7 @@ func New(cfg *config.Config, log *logger.Logger) http.Handler { //nolint:funlen, tplProps.Host = r.Header.Get("Host") // the value of the `Host` header } + // TODO: ADD SUPPORT FOR THE RANDOM TEMPLATE AND SO ON // try to find the code message and description in the config and if not - use the standard status text or fallback if desc, found := cfg.Codes.Find(code); found { tplProps.Message = desc.Message @@ -140,7 +141,7 @@ func New(cfg *config.Config, log *logger.Logger) http.Handler { //nolint:funlen, } } else { write(w, log, `The requested content format is not supported. -Please create an issue on the project's GitHub page to request support for it. +Please create an issue on the project's GitHub page to request support for this format. Supported formats: JSON, XML, HTML, Plain Text`) } diff --git a/internal/template/template.go b/internal/template/template.go index e89ecee..090a36a 100644 --- a/internal/template/template.go +++ b/internal/template/template.go @@ -11,6 +11,7 @@ import ( "time" "gh.tarampamp.am/error-pages/internal/appmeta" + "gh.tarampamp.am/error-pages/l10n" ) var builtInFunctions = template.FuncMap{ //nolint:gochecknoglobals @@ -99,6 +100,10 @@ var builtInFunctions = template.FuncMap{ //nolint:gochecknoglobals // retrieves the value of the environment variable named by the key: // `{{ env "SHELL" }}` // `/bin/bash` "env": os.Getenv, + + // returns the content of the JS file with a script for automatic error page localization: + // `{{ l10nScript }}` // `Object.defineProperty(window, ...` + "l10nScript": l10n.L10n, } func Render(content string, props Props) (string, error) { diff --git a/internal/template/template_test.go b/internal/template/template_test.go index 14ba215..a8a37de 100644 --- a/internal/template/template_test.go +++ b/internal/template/template_test.go @@ -11,6 +11,7 @@ import ( "gh.tarampamp.am/error-pages/internal/appmeta" "gh.tarampamp.am/error-pages/internal/template" + "gh.tarampamp.am/error-pages/l10n" ) func TestRender_BuiltInFunction(t *testing.T) { @@ -29,10 +30,6 @@ func TestRender_BuiltInFunction(t *testing.T) { giveTemplate: `{{ now.Unix }}`, wantResult: strconv.Itoa(int(time.Now().Unix())), }, - "now (time)": { - giveTemplate: `{{ now.Hour }}:{{ now.Minute }}:{{ now.Second }}`, - wantResult: time.Now().Format("15:4:5"), - }, "hostname": {giveTemplate: `{{ hostname }}`, wantResult: hostname}, "json (string)": {giveTemplate: `{{ json "test" }}`, wantResult: `"test"`}, "json (int)": {giveTemplate: `{{ json 42 }}`, wantResult: `42`}, @@ -54,6 +51,7 @@ func TestRender_BuiltInFunction(t *testing.T) { "strFields": {giveTemplate: `{{ strFields "foo bar baz" }}`, wantResult: `[foo bar baz]`}, "env (ok)": {giveTemplate: `{{ env "TEST_ENV_VAR" }}`, wantResult: "unit-test"}, "env (not found)": {giveTemplate: `{{ env "NOT_FOUND_ENV_VAR" }}`, wantResult: ""}, + "l10nScript": {giveTemplate: `{{ l10nScript }}`, wantResult: l10n.L10n()}, } { t.Run(name, func(t *testing.T) { require.NoError(t, os.Setenv("TEST_ENV_VAR", "unit-test")) diff --git a/l10n/.eslintrc.json b/l10n/.eslintrc.json deleted file mode 100644 index d73d14f..0000000 --- a/l10n/.eslintrc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": [ - "eslint:recommended" - ], - "parserOptions": { - "ecmaVersion": 2017 - }, - "env": { - "browser": true - } -} diff --git a/l10n/embed_test.go b/l10n/embed_test.go new file mode 100644 index 0000000..854c225 --- /dev/null +++ b/l10n/embed_test.go @@ -0,0 +1,14 @@ +package l10n_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "gh.tarampamp.am/error-pages/l10n" +) + +func TestL10n(t *testing.T) { + assert.NotEmpty(t, l10n.L10n()) + assert.Contains(t, l10n.L10n(), "data-l10n") +} diff --git a/l10n/enbed.go b/l10n/enbed.go new file mode 100644 index 0000000..93d6fe9 --- /dev/null +++ b/l10n/enbed.go @@ -0,0 +1,9 @@ +package l10n + +import _ "embed" + +//go:embed l10n.js +var content string + +// L10n returns the content of the JS file with a script for automatic error page localization. +func L10n() string { return content } diff --git a/l10n/l10n.js b/l10n/l10n.js index 4f8ec22..eaa04d7 100644 --- a/l10n/l10n.js +++ b/l10n/l10n.js @@ -1,942 +1,961 @@ Object.defineProperty(window, 'l10n', { - value: new function () { - // language codes list: <https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes> - const data = { // all keys should be in english (it is default/main locale) - 'Error': { - fr: 'Erreur', - ru: 'Ошибка', - uk: 'Помилка', - pt: 'Erro', - nl: 'Fout', - de: 'Fehler', - es: 'Error', - zh: '错误', - id: 'Kesalahan', - pl: 'Błąd', - }, - 'Good luck': { - fr: 'Bonne chance', - ru: 'Удачи', - uk: 'Успіхів', - pt: 'Boa sorte', - nl: 'Veel succes', - de: 'Viel Glück', - es: 'Buena Suerte', - zh: '祝好运', - id: 'Semoga berhasil!', - pl: 'Powodzenia', - }, - 'UH OH': { - fr: 'Oups', - ru: 'Ох', - uk: 'Упс', - pt: 'Ops', - nl: 'Oeps', - de: 'Hoppla', - es: 'Uy', - zh: '哎呀', - id: 'Ups', - pl: 'Ojej', - }, - 'Request details': { - fr: 'Détails de la requête', - ru: 'Детали запроса', - uk: 'Деталі запиту', - pt: 'Detalhes da solicitação', - nl: 'Details van verzoek', - de: 'Details der Anfrage', - es: 'Detalles de la petición', - zh: '请求详情', - id: 'Rincian permintaan', - pl: 'Poproś o szczegóły', - }, - 'Double-check the URL': { - fr: 'Vérifiez l’URL', - ru: 'Дважды проверьте URL', - uk: 'Двічі перевіряйте URL-адресу', - pt: 'Verifique novamente a URL', - nl: 'Controleer de URL', - de: 'Überprüfen Sie die URL', - es: 'Verifique la url', - zh: '请再次检查地址', - id: 'Periksa URL', - pl: 'Sprawdź adres URL', - }, - 'Alternatively, go back': { - fr: 'Essayer de revenir en arrière', - ru: 'Или можете вернуться назад', - uk: 'Або можете повернутися назад', - pt: "Como alternativa, tente voltar", - nl: 'Of ga terug', - de: 'Alternativ gehen Sie zurück', - es: 'Como alternativa, vuelva atrás', - zh: '或返回上一页', - id: 'Atau, kembali', - pl: 'Alternatywnie wróć', - }, - 'Here\'s what might have happened': { - fr: 'Voici ce qui aurait pu se passer', - ru: 'Из-за чего это могло случиться', - uk: 'Ось що могло трапитися', - pt: 'Aqui está o que pode ter acontecido', - nl: 'Wat er gebeurd kan zijn', - de: 'Folgendes könnte passiert sein', - es: 'Esto es lo que ha podido pasar', - zh: '可能原因有', - id: 'Inilah yang bisa saja terjadi', - pl: 'Oto, co mogło się wydarzyć', - }, - 'You may have mistyped the URL': { - fr: 'Vous avez peut-être mal tapé l’URL', - ru: 'Вы могли ошибиться в URL', - uk: 'Ви могли помилитися в URL-адресі', - pt: 'Você pode ter digitado incorretamente a URL', - nl: 'De URL bevat een typefout', - de: 'Möglicherweise haben Sie die URL falsch eingegeben', - es: 'Quizá ha escrito mal la URL', - zh: '您可能输入了错误的地址', - id: 'Anda mungkin tersalah memasukkan URL', - pl: 'Być może błędnie wpisałeś adres URL', - }, - 'The site was moved': { - fr: 'Le site a été déplacé', - ru: 'Сайт был перемещён', - uk: 'Сайт був переміщений', - pt: 'O site foi movido', - nl: 'De site is verplaatst', - de: 'Die Seite wurde verschoben', - es: 'El sitio se ha trasladado', - zh: '站点已被转移', - id: 'Halaman dipindahkan', - pl: 'Witryna została przeniesiona', - }, - 'It was never here': { - fr: 'Il n’a jamais été ici', - ru: 'Он никогда не был здесь', - uk: 'Він ніколи не був тут', - pt: 'Nunca esteve aqui', - nl: 'Het was hier nooit', - de: 'Es war nie hier', - es: 'Nunca ha estado aquí', - zh: '站点从未存在', - id: 'Itu Tidak pernah di sini', - pl: 'Nigdy jej nie było', - }, - 'Bad Request': { - fr: 'Mauvaise requête', - ru: 'Некорректный запрос', - uk: 'Хибний запит', - pt: 'Requisição inválida', - nl: 'Foutieve anvraag', - de: 'Fehlerhafte Anfrage', - es: 'Petición inválida', - zh: '错误请求', - id: 'Permintaan yang salah', - pl: 'Nieprawidłowe żądanie', - }, - 'The server did not understand the request': { - fr: 'Le serveur ne comprend pas la requête', - ru: 'Сервер не смог обработать запрос из-за ошибки в нём', - uk: 'Сервер не зміг обробити запит через помилку в ньому', - pt: 'O servidor não entendeu a solicitação', - nl: 'De server begreep het verzoek niet', - de: 'Der Server hat die Anfrage nicht verstanden', - es: 'El servidor no entendió la petición', - zh: '服务器不理解该请求', - id: 'Server tidak memahami permintaan', - pl: 'Serwer nie zrozumiał żądania', - }, - 'Unauthorized': { - fr: 'Non autorisé', - ru: 'Запрос не авторизован', - uk: 'Несанкціонований доступ', - pt: 'Não autorizado', - nl: 'Niet geautoriseerd', - de: 'Nicht autorisiert', - es: 'No autorizado', - zh: '未经授权', - id: 'Tidak diotorisasi', - pl: 'Nieautoryzowany', - }, - 'The requested page needs a username and a password': { - fr: 'La page demandée nécessite un nom d’utilisateur et un mot de passe', - ru: 'Для доступа к странице требуется логин и пароль', - uk: 'Щоб отримати доступ до сторінки, потрібний логін та пароль', - pt: 'A página solicitada precisa de um nome de usuário e uma senha', - nl: 'De pagina heeft een gebruikersnaam en wachtwoord nodig', - de: 'Die angeforderte Seite benötigt einen Benutzernamen und ein Passwort', - es: 'La página solicitada necesita un usuario y una contraseña', - zh: '请求的页面需要用户名和密码', - id: 'Halaman yang diminta membutuhkan nama pengguna dan kata sandi', - pl: 'Żądana strona wymaga podania nazwy użytkownika i hasła', - }, - 'Forbidden': { - fr: 'Interdit', - ru: 'Запрещено', - uk: 'Заборонено', - pt: 'Proibido', - nl: 'Verboden', - de: 'Verboten', - es: 'Prohibido', - zh: '禁止访问', - id: 'Dilarang', - pl: 'Zabroniony', - }, - 'Access is forbidden to the requested page': { - fr: 'Accès interdit à la page demandée', - ru: 'Доступ к странице запрещён', - uk: 'Доступ до сторінки заборонено', - pt: 'É proibido o acesso à página solicitada', - nl: 'Toegang tot de pagina is verboden', - de: 'Der Zugriff auf die angeforderte Seite ist verboten', - es: 'El acceso está prohibido para la página solicitada', - zh: '禁止访问请求的页面', - id: 'Akses dilarang ke halaman yang diminta', - pl: 'Dostęp do żądanej strony jest zabroniony', - }, - 'Not Found': { - fr: 'Introuvable', - ru: 'Страница не найдена', - uk: 'Сторінку не знайдено', - pt: 'Não encontrado', - nl: 'Niet gevonden', - de: 'Nicht gefunden', - es: 'No encontrado', - zh: '未找到', - id: 'Tidak ditemukan', - pl: 'Nie znaleziono', - }, - 'The server can not find the requested page': { - fr: 'Le serveur ne peut trouver la page demandée', - ru: 'Сервер не смог найти запрашиваемую страницу', - uk: 'Сервер не зміг знайти запитану сторінку', - pt: 'O servidor não consegue encontrar a página solicitada', - nl: 'De server kan de pagina niet vinden', - de: 'Der Server kann die angeforderte Seite nicht finden', - es: 'El servidor no puede encontrar la página solicitada', - zh: '服务器找不到请求的页面', - id: 'Server tidak dapat menemukan halaman yang diminta', - pl: 'Serwer nie może znaleźć żądanej strony', - }, - 'Method Not Allowed': { - fr: 'Méthode Non Autorisée', - ru: 'Метод не поддерживается', - uk: 'Неприпустимий метод', - pt: 'Método não permitido', - nl: 'Methode niet toegestaan', - de: 'Methode nicht erlaubt', - es: 'Método no permitido', - zh: '方法不被允许', - id: 'Metode tidak diizinkan', - pl: 'Niedozwolona metoda', - }, - 'The method specified in the request is not allowed': { - fr: 'La méthode spécifiée dans la requête n’est pas autorisée', - ru: 'Указанный в запросе метод не поддерживается', - uk: 'Метод, зазначений у запиті, не підтримується', - pt: 'O método especificado na solicitação não é permitido', - nl: 'De methode in het verzoek is niet toegestaan', - de: 'Die in der Anfrage angegebene Methode ist nicht zulässig', - es: 'El método especificado en la petición no está permitido', - zh: '请求指定的方法不被允许', - id: 'Metode dalam permintaan tidak diizinkan', - pl: 'Metoda określona w żądaniu jest niedozwolona', - }, - 'Proxy Authentication Required': { - fr: 'Authentification proxy requise', - ru: 'Нужна аутентификация прокси', - uk: 'Потрібна ідентифікація проксі', - pt: 'Autenticação de proxy necessária', - nl: 'Authenticatie op de proxyserver verplicht', - de: 'Proxy-Authentifizierung benötigt', - es: 'Autenticación de proxy requerida', - zh: '需要代理服务器身份验证', - id: 'Diperlukan otentikasi proxy', - pl: 'Wymagane uwierzytelnianie proxy', - }, - 'You must authenticate with a proxy server before this request can be served': { - fr: 'Vous devez vous authentifier avec un serveur proxy avant que cette requête puisse être servie', - ru: 'Вы должны быть авторизованы на прокси сервере для обработки этого запроса', - uk: 'Ви повинні увійти до проксі-сервера для обробки цього запиту', - pt: 'Você deve se autenticar com um servidor proxy antes que esta solicitação possa ser atendida', - nl: 'Je moet authenticeren bij een proxyserver voordat dit verzoek uitgevoerd kan worden', - de: 'Sie müssen sich bei einem Proxy-Server authentifizieren, bevor diese Anfrage bedient werden kann', - es: 'Debes autentificarte con un servidor proxy antes de que esta petición pueda ser atendida', - zh: '您必须对代理服务器进行身份验证,然后才能让请求得到处理', - id: 'Anda harus mengautentikasi dengan server proxy sebelum permintaan ini dapat dilayani', - pl: 'Musisz uwierzytelnić się na serwerze proxy, zanim to żądanie będzie mogło zostać obsłużone', - }, - 'Request Timeout': { - fr: 'Requête expiré', - ru: 'Истекло время ожидания', - uk: 'Вичерпано час очікування', - pt: 'Tempo limite de solicitação excedido', - nl: 'Aanvraagtijd verstreken', - de: 'Zeitüberschreitung der Anforderung', - es: 'Tiempo límite de la petición excedido', - zh: '请求超时', - id: 'Meminta batas waktu', - pl: 'Przekroczenie limitu czasu żądania', - }, - 'The request took longer than the server was prepared to wait': { - fr: 'La requête prend plus de temps que prévu', - ru: 'Отправка запроса заняла слишком много времени', - uk: 'Надсилання запиту зайняло надто багато часу', - pt: 'A solicitação demorou mais do que o servidor estava preparado para esperar', - nl: 'Het verzoek duurde langer dan de server wilde wachten', - de: 'Die Anfrage hat länger gedauert, als der Server bereit war zu warten', - es: 'La petición esta tardando más de lo que el servidor estaba preparado para esperar', - zh: '请求用时超过了服务器设置的最长等待时间', - id: 'Permintaan memakan waktu lebih lama dari yang bisa ditunggu oleh server', - pl: 'Żądanie trwało dłużej niż serwer był gotowy czekać', - }, - 'Conflict': { - fr: 'Conflit', - ru: 'Конфликт', - uk: 'Конфлікт', - pt: 'Conflito', - nl: 'Conflict', - de: 'Konflikt', - es: 'Conflicto', - zh: '冲突', - id: 'Konflik', - pl: 'Konflikt', - }, - 'The request could not be completed because of a conflict': { - fr: 'La requête n’a pas pu être complétée à cause d’un conflit', - ru: 'Запрос не может быть обработан из-за конфликта', - uk: 'Запит не може бути оброблений через конфлікт', - pt: 'A solicitação não pôde ser concluída devido a um conflito', - nl: 'Het verzoek kon niet worden verwerkt vanwege een conflict', - de: 'Die Anfrage konnte aufgrund eines Konflikts nicht abgeschlossen werden', - es: 'La petición no ha podido ser completada por un conflicto', - zh: '由于冲突,请求无法完成', - id: 'Permintaan tidak dapat diselesaikan karena adanya konflik', - pl: 'Żądanie nie mogło zostać wykonane z powodu konfliktu', - }, - 'Gone': { - fr: 'Supprimé', - ru: 'Удалено', - uk: 'Вилучений', - pt: 'Removido', - nl: 'Verdwenen', - de: 'Verschwunden', - es: 'Eliminado', - zh: '已移除', - id: 'Menghilang', - pl: 'Usunięto', - }, - 'The requested page is no longer available': { - fr: 'La page demandée n’est plus disponible', - ru: 'Запрошенная страница была удалена', - uk: 'Запитувана сторінка більше не доступна', - pt: 'A página solicitada não está mais disponível', - nl: 'De pagina is niet langer beschikbaar', - de: 'Die angeforderte Seite ist nicht mehr verfügbar', - es: 'La página solicitada no está ya disponible', - zh: '请求的页面不再可用', - id: 'Halaman yang diminta tidak lagi tersedia', - pl: 'Żądana strona nie jest już dostępna', - }, - 'Length Required': { - fr: 'Longueur requise', - ru: 'Необходима длина', - uk: 'Потрібно вказати довжину', - pt: 'Content-Length necessário', - nl: 'Lengte benodigd', - de: 'Länge benötigt', - es: 'Longitud requerida', - zh: '需要长度', - id: 'Panjang yang diperlukan', - pl: 'Wymagana długość', - }, - 'The "Content-Length" is not defined. The server will not accept the request without it': { - fr: 'Le "Content-Length" n’est pas défini. Le serveur ne prendra pas en compte la requête', - ru: 'Заголовок "Content-Length" не был передан. Сервер не может обработать запрос без него', - uk: 'Заголовок "Content-Length" не був переданий. Сервер не може обробити запит без нього', - pt: 'O "Content-Length" não está definido. O servidor não aceitará a solicitação sem ele', - nl: 'De "Content-Length" is niet gespecificeerd. De server accepteert het verzoek niet zonder', - de: 'Die "Content-Length" ist nicht definiert. Ohne sie akzeptiert der Server die Anfrage nicht', - es: 'El "Content-Legth" no eta definido. Este servidor no aceptará la petición sin él', - zh: '未指定Content-Length(内容长度)。服务器将不接受不包含此头信息的请求', - id: '"Content-Length" tidak ditentukan. Server tidak akan menerima permintaan tanpa itu', - pl: 'Wartość "Content-Length" nie jest zdefiniowana. Serwer nie zaakceptuje żądania bez tego parametru', - }, - 'Precondition Failed': { - fr: 'Échec de la condition préalable', - ru: 'Условие ложно', - uk: 'Збій під час обробки попередньої умови', - pt: 'Falha na pré-condição', - nl: 'Niet voldaan aan vooraf gestelde voorwaarde', - de: 'Vorbedingung fehlgeschlagen', - es: 'Precondición fallida', - zh: '前置条件判定失败', - pl: 'Niespełnienie warunku wstępnego', - }, - 'The pre condition given in the request evaluated to false by the server': { - fr: 'La précondition donnée dans la requête a été évaluée comme étant fausse par le serveur', - ru: 'Ни одно из условных полей заголовка запроса не было выполнено', - uk: 'Жодна з передумов запиту не була виконана', - pt: 'A pré-condição dada na solicitação avaliada como falsa pelo servidor', - nl: 'De vooraf gestelde voorwaarde is afgewezen door de server', - de: 'Die in der Anfrage angegebene Vorbedingung wird vom Server als falsch bewertet', - es: 'La precondición ha sido evaluada como negativa para esta petición por el servidor', - zh: '服务器评估请求中给出的前置条件的结果为false(假)', - id: 'Prakondisi gagal', - pl: 'Warunek wstępny podany w żądaniu został oceniony przez serwer jako nieprawidłowy', - }, - 'Payload Too Large': { - fr: 'Charge trop volumineuse', - ru: 'Слишком большой запрос', - uk: 'Занадто великий запит', - pt: 'Payload muito grande', - nl: 'Aanvraag te grood', - de: 'Anfrage zu groß', - es: 'Carga demasiado grande', - zh: '请求体过大', - id: 'Muatan terlalu besar', - pl: 'Żądanie jest zbyt duże', - }, - 'The server will not accept the request, because the request entity is too large': { - fr: 'Le serveur ne prendra pas en compte la requête, car l’entité de la requête est trop volumineuse', - ru: 'Сервер не может обработать запрос, так как он слишком большой', - uk: 'Сервер не може обробити запит, оскільки він занадто великий', - pt: 'O servidor não aceitará a solicitação porque a entidade da solicitação é muito grande', - nl: 'De server accepteert het verzoek niet omdat de aanvraag te groot is', - de: 'Der Server akzeptiert die Anfrage nicht, da die Datenmenge zu groß ist', - es: 'El servidor no aceptará esta petición, porque la carga es demasiado grande', - zh: '请求体过大,服务器将不接受该请求', - id: 'Server tidak akan menerima permintaan, karena entitas permintaan terlalu besar', - pl: 'Serwer nie zaakceptuje żądania, ponieważ żądanie jest zbyt duże', - }, - 'Requested Range Not Satisfiable': { - fr: 'Requête non satisfaisante', - ru: 'Диапазон не достижим', - uk: 'Запитуваний діапазон недосяжний', - pt: 'Intervalo Solicitado Não Satisfatório', - nl: 'Aangevraagd gedeelte niet opvraagbaar', - de: 'Anfrage-Bereich nicht erfüllbar', - es: 'Intervalo solicitado no satisfactorio', - zh: '不满足请求范围', - id: 'Rentang yang diminta tidak dapat dipenuhi', - pl: 'Żądany zakres nie jest satysfakcjonujący', - }, - 'The requested byte range is not available and is out of bounds': { - fr: 'Le byte range demandé n’est pas disponible et est hors des limites', - ru: 'Запрошенный диапазон данных недоступен или вне допустимых пределов', - uk: 'Описаний діапазон даних недоступний або поза допустимими межами', - pt: 'O intervalo de bytes solicitado não está disponível e está fora dos limites', - nl: 'De aangevraagde bytes zijn buiten het limiet', - de: 'Der angefragte Teilbereich der Ressource existiert nicht oder ist ungültig', - es: 'El intervalo de bytes requerido no está disponible o se encuentra fuera de los límites', - zh: '请求的字节范围不可用,超出边界', - id: 'Rentang byte yang diminta tidak tersedia dan di luar batas', - pl: 'Żądany zakres bajtów nie jest dostępny i znajduje się poza zakresem', - }, - 'I\'m a teapot': { - fr: 'Je suis une théière', - ru: 'Я чайник', - uk: 'Я чайник', - pt: 'Eu sou um bule', - nl: 'Ik ben een theepot', - de: 'Ich bin eine Teekanne', - es: 'Soy una tetera', - zh: '我是一只茶壶', - id: 'Saya adalah teko', - pl: 'Jestem czajniczkiem', - }, - 'Attempt to brew coffee with a teapot is not supported': { - fr: 'Tenter de préparer du café avec une théière n’est pas pris en charge', - ru: 'Попытка заварить кофе в чайнике обречена на фиаско', - uk: 'Спроба заварити каву в чайнику приречена на фіаско', - pt: 'A tentativa de preparar café com um bule não é suportada', - nl: 'Koffie maken met een theepot is niet ondersteund', - de: 'Der Versuch, Kaffee mit einer Teekanne zuzubereiten, wird nicht unterstützt', - es: 'Intentar hacer un café en una tetera no está soportado', - zh: '用茶壶泡咖啡不受支持', - id: 'Upaya menyeduh kopi dengan teko tidak didukung', - pl: 'Próba zaparzenia kawy za pomocą czajniczka nie jest obsługiwana', - }, - 'Too Many Requests': { - fr: 'Trop de requêtes', - ru: 'Слишком много запросов', - uk: 'Занадто багато запитів', - pt: 'Excesso de solicitações', - nl: 'Te veel requests', - de: 'Zu viele Anfragen', - es: 'Demasiadas peticiones', - zh: '请求过多', - id: 'Terlalu banyak permintaan', - pl: 'Zbyt wiele żądań', - }, - 'Too many requests in a given amount of time': { - fr: 'Trop de requêtes dans un délai donné', - ru: 'Отправлено слишком много запросов за короткое время', - uk: 'Надіслано занадто багато запитів за короткий проміжок час', - pt: 'Excesso de solicitações em um determinado período de tempo', - nl: 'Te veel verzoeken binnen een bepaalde tijd', - de: 'Der Client hat zu viele Anfragen in einem bestimmten Zeitraum gesendet', - es: 'Demasiadas peticiones en un determinado periodo de tiempo', - zh: '在给定的时间内发送了过多请求', - id: 'Terlalu banyak permintaan dalam waktu tertentu', - pl: 'Zbyt wiele żądań w określonym czasie', - }, - 'Internal Server Error': { - fr: 'Erreur interne du serveur', - ru: 'Внутренняя ошибка сервера', - uk: 'Внутрішня помилка сервера', - pt: 'Erro do Servidor Interno', - nl: 'Interne serverfout', - de: 'Interner Server-Fehler', - es: 'Error Interno', - zh: '内部服务器错误', - id: 'Kesalahan server internal', - pl: 'Wewnętrzny błąd serwera', - }, - 'The server met an unexpected condition': { - fr: 'Le serveur a rencontré une condition inattendue', - ru: 'Произошло что-то неожиданное на сервере', - uk: 'На сервері відбулось щось неочікуване', - pt: 'O servidor encontrou uma condição inesperada', - nl: 'De server ondervond een onverwachte conditie', - de: 'Der Server hat einen internen Fehler festgestellt', - es: 'El servidor ha encontrado una condición no esperada', - zh: '服务器遇到了意外情况', - id: 'Server mengalami kondisi yang tidak terduga', - pl: 'Serwer napotkał nieoczekiwany stan', - }, - 'Bad Gateway': { - fr: 'Mauvaise passerelle', - ru: 'Ошибка шлюза', - uk: 'Помилка шлюзу', - pt: 'Gateway inválido', - nl: 'Ongeldige Gateway', - de: 'Fehlerhaftes Gateway', - es: 'Puerta de enlace no valida', - zh: '无效网关', - id: 'Gateway yang buruk', - pl: 'Błąd bramki', - }, - 'The server received an invalid response from the upstream server': { - fr: 'Le serveur a reçu une réponse invalide du serveur distant', - ru: 'Сервер получил некорректный ответ от вышестоящего сервера', - uk: 'Сервер отримав невірну відповідь від попереднього сервера', - pt: 'O servidor recebeu uma resposta inválida do servidor upstream', - nl: 'De server ontving een ongeldig antwoord van een bovenliggende server', - de: 'Der Server hat eine ungültige Antwort vom Upstream-Server erhalten', - es: 'El servidor ha recibido una respuesta no válida del servidor de origen', - zh: '服务器从上游服务器收到了无效的响应', - id: 'Server menerima respons yang tidak valid dari server induk', - pl: 'Serwer otrzymał nieprawidłową odpowiedź od serwera nadrzędnego', - }, - 'Service Unavailable': { - fr: 'Service indisponible', - ru: 'Сервис недоступен', - uk: 'Сервіс недоступний', - pt: 'Serviço não disponível', - nl: 'Dienst niet beschikbaar', - de: 'Dienst nicht verfügbar', - es: 'Servicio no disponible', - zh: '服务不可用', - id: 'Layanan tidak tersedia', - pl: 'Serwis niedostępny', - }, - 'The server is temporarily overloading or down': { - fr: 'Le serveur est temporairement en surcharge ou indisponible', - ru: 'Сервер временно не может обрабатывать запросы по техническим причинам', - uk: 'Сервер тимчасово не може обробляти запити з технічних причин', - pt: 'O servidor está temporariamente sobrecarregado ou inativo', - nl: 'De server is tijdelijk overbelast of niet bereikbaar', - de: 'Der Server ist vorübergehend überlastet oder ausgefallen', - es: 'El servidor está temporalmente sobrecargado o inactivo', - zh: '服务器暂时过载或不可用', - id: 'Server untuk sementara kelebihan beban atau tidak tersedia', - pl: 'Serwer jest tymczasowo przeciążony lub wyłączony', - }, - 'Gateway Timeout': { - fr: 'Expiration Passerelle', - ru: 'Шлюз не отвечает', - uk: 'Шлюз не відповідає', - pt: 'Tempo limite do gateway excedido', - nl: 'Gateway Verlopen', - de: 'Gateway Zeitüberschreitung', - es: 'Tiempo límite de puerta de enlace excedido', - zh: '网关超时', - id: 'Batas waktu gateway', - pl: 'Przekroczenie limitu czasu bramki', - }, - 'The gateway has timed out': { - fr: 'Le temps d’attente de la passerelle est dépassé', - ru: 'Сервер не дождался ответа от вышестоящего сервера', - uk: 'У шлюзу закінчився час очікування', - pt: 'O gateway esgotou o tempo limite', - nl: 'De verbinding naar de bovenliggende server is verlopen', - de: 'Das Zeitlimit für den Verbindungsaufbau mit dem Upstream-Server ist abgelaufen', - es: 'La puerta de enlace ha sobrepasado el tiempo límite', - zh: '网关响应已经超时', - id: 'Sambungan ke server induk telah kedaluwarsa', - pl: 'Bramka przekroczyła limit czasu', - }, - 'HTTP Version Not Supported': { - fr: 'Version HTTP non prise en charge', - ru: 'Версия HTTP не поддерживается', - uk: 'Версія НТТР не підтримується', - pt: 'Versão HTTP não suportada', - nl: 'HTTP-versie wordt niet ondersteunt', - de: 'HTTP-Version wird nicht unterstützt', - es: 'Versión de HTTP no soportada', - zh: 'HTTP版本不受支持', - id: 'Versi HTTP tidak didukung', - pl: 'Wersja HTTP nie jest obsługiwana', - }, - 'The server does not support the "http protocol" version': { - fr: 'Le serveur ne supporte pas la version du protocole HTTP', - ru: 'Сервер не поддерживает запрошенную версию HTTP протокола', - uk: 'Сервер не підтримує запитану версію HTTP-протоколу', - pt: 'O servidor não suporta a versão do protocolo HTTP', - nl: 'De server ondersteunt deze HTTP-versie niet', - de: 'Der Server unterstützt die HTTP-Protokoll-Version nicht', - es: 'El servidor no soporta la versión del protocolo HTTP', - zh: '服务器不支持该HTTP协议版本', - id: 'Server tidak mendukung versi HTTP ini', - pl: 'Serwer nie obsługuje wersji "protokołu http"', - }, + value: new function () { + const tokenSerializationRe = /[^a-z0-9]/g; - 'Host': { - fr: 'Hôte', - ru: 'Хост', - uk: 'Хост', - pt: 'Hospedeiro', - nl: 'Host', - de: 'Host', - es: 'Host', - zh: '主机', - id: 'Host', - pl: 'Host', - }, - 'Original URI': { - fr: 'URI d’origine', - ru: 'Исходный URI', - uk: 'Вихідний URI', - pt: 'URI original', - nl: 'Originele URI', - de: 'Originale URI', - es: 'URI original', - zh: '原始URI', - id: 'URL asli', - pl: 'Oryginalny URI', - }, - 'Forwarded for': { - fr: 'Transmis pour', - ru: 'Перенаправлен', - uk: 'Перенаправлений', - pt: 'Encaminhado para', - nl: 'Doorgestuurd voor', - de: 'Weitergeleitet für', - es: 'Remitido para', - zh: '转发自', - id: 'Diteruskan untuk', - pl: 'Przekazane do', - }, - 'Namespace': { - fr: 'Espace de noms', - ru: 'Пространство имён', - uk: 'Простір імен', - pt: 'Namespace', - nl: 'Elementnaam', - de: 'Namensraum', - es: 'Namespace', - zh: '命名空间', - id: 'Ruang nama', - pl: 'Przestrzeń nazw', - }, - 'Ingress name': { - fr: 'Nom ingress', - ru: 'Имя Ingress', - uk: 'Ім\'я входу', - pt: 'Nome Ingress', - nl: 'Ingress naam', - de: 'Ingress Name', - es: 'Nombre Ingress', - zh: '入口名', - id: 'Nama ingress', - pl: 'Nazwa wejścia', - }, - 'Service name': { - fr: 'Nom du service', - ru: 'Имя сервиса', - uk: 'Ім\'я сервісу', - pt: 'Nome do Serviço', - nl: 'Service naam', - de: 'Service Name', - es: 'Nombre del servicio', - zh: '服务名', - id: 'Nama layanan', - pl: 'Nazwa usługi', - }, - 'Service port': { - fr: 'Port du service', - ru: 'Порт сервиса', - uk: 'Порт сервісу', - pt: 'Porta do serviço', - nl: 'Service poort', - de: 'Service Port', - es: 'Puerto del servicio', - zh: '服务端口', - id: 'Port layanan', - pl: 'Port usługi', - }, - 'Request ID': { - fr: 'Identifiant de la requête', - ru: 'ID запроса', - uk: 'ID запиту', - pt: 'ID da solicitação', - nl: 'ID van het verzoek', - de: 'Anfrage ID', - es: 'ID de la petición', - zh: '请求ID', - id: 'ID permintaan', - pl: 'Identyfikator żądania', - }, - 'Timestamp': { - fr: 'Horodatage', - ru: 'Временная метка', - uk: 'Мітка часу', - pt: 'Timestamp', - nl: 'Tijdstempel', - de: 'Zeitstempel', - es: 'Timestamp', - zh: '时间戳', - id: 'Cap waktu', - pl: 'Sygnatura czasowa', - }, + /** + * @param {string} token + * @return {string} + */ + const tkn = function (token) { + return token.toLowerCase().replaceAll(tokenSerializationRe, ''); + }; - 'client-side error': { - fr: 'Erreur Client', - ru: 'ошибка на стороне клиента', - uk: 'помилка на стороні клієнта', - pt: 'erro do lado do cliente', - nl: 'fout aan de gebruikerskant', - de: 'Clientseitiger Fehler', - es: 'Error del lado del cliente', - zh: '客户端错误', - id: 'Kesalahan sisi klien', - pl: 'błąd po stronie klienta', - }, - 'server-side error': { - fr: 'Erreur Serveur', - ru: 'ошибка на стороне сервера', - uk: 'помилка на стороні сервера', - pt: 'erro do lado do servidor', - nl: 'fout aan de serverkant', - de: 'Serverseitiger Fehler', - es: 'Error del lado del servidor', - zh: '服务端错误', - id: 'Kesalahan sisi server', - pl: 'błąd po stronie serwera', - }, + /** + * Each **key** should be in English (this is the default/main locale). + * + * @link https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes language codes list + * + * @type {Map<string, Map<'fr'|'ru'|'uk'|'pt'|'nl'|'de'|'es'|'zh'|'id'|'pl', string>>} + */ + const data = Object.freeze(new Map([ + [tkn('Error'), new Map([ + ['fr', 'Erreur'], + ['ru', 'Ошибка'], + ['uk', 'Помилка'], + ['pt', 'Erro'], + ['nl', 'Fout'], + ['de', 'Fehler'], + ['es', 'Error'], + ['zh', '错误'], + ['id', 'Kesalahan'], + ['pl', 'Błąd'], + ])], + [tkn('Good luck'), new Map([ + ['fr', 'Bonne chance'], + ['ru', 'Удачи'], + ['uk', 'Успіхів'], + ['pt', 'Boa sorte'], + ['nl', 'Veel succes'], + ['de', 'Viel Glück'], + ['es', 'Buena Suerte'], + ['zh', '祝好运'], + ['id', 'Semoga berhasil!'], + ['pl', 'Powodzenia'], + ])], + [tkn('UH OH'), new Map([ + ['fr', 'Oups'], + ['ru', 'Ох'], + ['uk', 'Упс'], + ['pt', 'Ops'], + ['nl', 'Oeps'], + ['de', 'Hoppla'], + ['es', 'Uy'], + ['zh', '哎呀'], + ['id', 'Ups'], + ['pl', 'Ojej'], + ])], + [tkn('Request details'), new Map([ + ['fr', 'Détails de la requête'], + ['ru', 'Детали запроса'], + ['uk', 'Деталі запиту'], + ['pt', 'Detalhes da solicitação'], + ['nl', 'Details van verzoek'], + ['de', 'Details der Anfrage'], + ['es', 'Detalles de la petición'], + ['zh', '请求详情'], + ['id', 'Rincian permintaan'], + ['pl', 'Poproś o szczegóły'], + ])], + [tkn('Double-check the URL'), new Map([ + ['fr', 'Vérifiez l’URL'], + ['ru', 'Дважды проверьте URL'], + ['uk', 'Двічі перевіряйте URL-адресу'], + ['pt', 'Verifique novamente a URL'], + ['nl', 'Controleer de URL'], + ['de', 'Überprüfen Sie die URL'], + ['es', 'Verifique la url'], + ['zh', '请再次检查地址'], + ['id', 'Periksa URL'], + ['pl', 'Sprawdź adres URL'], + ])], + [tkn('Alternatively, go back'), new Map([ + ['fr', 'Essayer de revenir en arrière'], + ['ru', 'Или можете вернуться назад'], + ['uk', 'Або можете повернутися назад'], + ['pt', "Como alternativa, tente voltar"], + ['nl', 'Of ga terug'], + ['de', 'Alternativ gehen Sie zurück'], + ['es', 'Como alternativa, vuelva atrás'], + ['zh', '或返回上一页'], + ['id', 'Atau, kembali'], + ['pl', 'Alternatywnie wróć'], + ])], + [tkn("Here's what might have happened"), new Map([ + ['fr', 'Voici ce qui aurait pu se passer'], + ['ru', 'Из-за чего это могло случиться'], + ['uk', 'Ось що могло трапитися'], + ['pt', 'Aqui está o que pode ter acontecido'], + ['nl', 'Wat er gebeurd kan zijn'], + ['de', 'Folgendes könnte passiert sein'], + ['es', 'Esto es lo que ha podido pasar'], + ['zh', '可能原因有'], + ['id', 'Inilah yang bisa saja terjadi'], + ['pl', 'Oto, co mogło się wydarzyć'], + ])], + [tkn('You may have mistyped the URL'), new Map([ + ['fr', 'Vous avez peut-être mal tapé l’URL'], + ['ru', 'Вы могли ошибиться в URL'], + ['uk', 'Ви могли помилитися в URL-адресі'], + ['pt', 'Você pode ter digitado incorretamente a URL'], + ['nl', 'De URL bevat een typefout'], + ['de', 'Möglicherweise haben Sie die URL falsch eingegeben'], + ['es', 'Quizá ha escrito mal la URL'], + ['zh', '您可能输入了错误的地址'], + ['id', 'Anda mungkin tersalah memasukkan URL'], + ['pl', 'Być może błędnie wpisałeś adres URL'], + ])], + [tkn('The site was moved'), new Map([ + ['fr', 'Le site a été déplacé'], + ['ru', 'Сайт был перемещён'], + ['uk', 'Сайт був переміщений'], + ['pt', 'O site foi movido'], + ['nl', 'De site is verplaatst'], + ['de', 'Die Seite wurde verschoben'], + ['es', 'El sitio se ha trasladado'], + ['zh', '站点已被转移'], + ['id', 'Halaman dipindahkan'], + ['pl', 'Witryna została przeniesiona'], + ])], + [tkn('It was never here'), new Map([ + ['fr', 'Il n’a jamais été ici'], + ['ru', 'Он никогда не был здесь'], + ['uk', 'Він ніколи не був тут'], + ['pt', 'Nunca esteve aqui'], + ['nl', 'Het was hier nooit'], + ['de', 'Es war nie hier'], + ['es', 'Nunca ha estado aquí'], + ['zh', '站点从未存在'], + ['id', 'Itu Tidak pernah di sini'], + ['pl', 'Nigdy jej nie było'], + ])], + [tkn('Bad Request'), new Map([ + ['fr', 'Mauvaise requête'], + ['ru', 'Некорректный запрос'], + ['uk', 'Хибний запит'], + ['pt', 'Requisição inválida'], + ['nl', 'Foutieve anvraag'], + ['de', 'Fehlerhafte Anfrage'], + ['es', 'Petición inválida'], + ['zh', '错误请求'], + ['id', 'Permintaan yang salah'], + ['pl', 'Nieprawidłowe żądanie'], + ])], + [tkn('The server did not understand the request'), new Map([ + ['fr', 'Le serveur ne comprend pas la requête'], + ['ru', 'Сервер не смог обработать запрос из-за ошибки в нём'], + ['uk', 'Сервер не зміг обробити запит через помилку в ньому'], + ['pt', 'O servidor não entendeu a solicitação'], + ['nl', 'De server begreep het verzoek niet'], + ['de', 'Der Server hat die Anfrage nicht verstanden'], + ['es', 'El servidor no entendió la petición'], + ['zh', '服务器不理解该请求'], + ['id', 'Server tidak memahami permintaan'], + ['pl', 'Serwer nie zrozumiał żądania'], + ])], + [tkn('Unauthorized'), new Map([ + ['fr', 'Non autorisé'], + ['ru', 'Запрос не авторизован'], + ['uk', 'Несанкціонований доступ'], + ['pt', 'Não autorizado'], + ['nl', 'Niet geautoriseerd'], + ['de', 'Nicht autorisiert'], + ['es', 'No autorizado'], + ['zh', '未经授权'], + ['id', 'Tidak diotorisasi'], + ['pl', 'Nieautoryzowany'], + ])], + [tkn('The requested page needs a username and a password'), new Map([ + ['fr', 'La page demandée nécessite un nom d’utilisateur et un mot de passe'], + ['ru', 'Для доступа к странице требуется логин и пароль'], + ['uk', 'Щоб отримати доступ до сторінки, потрібний логін та пароль'], + ['pt', 'A página solicitada precisa de um nome de usuário e uma senha'], + ['nl', 'De pagina heeft een gebruikersnaam en wachtwoord nodig'], + ['de', 'Die angeforderte Seite benötigt einen Benutzernamen und ein Passwort'], + ['es', 'La página solicitada necesita un usuario y una contraseña'], + ['zh', '请求的页面需要用户名和密码'], + ['id', 'Halaman yang diminta membutuhkan nama pengguna dan kata sandi'], + ['pl', 'Żądana strona wymaga podania nazwy użytkownika i hasła'], + ])], + [tkn('Forbidden'), new Map([ + ['fr', 'Interdit'], + ['ru', 'Запрещено'], + ['uk', 'Заборонено'], + ['pt', 'Proibido'], + ['nl', 'Verboden'], + ['de', 'Verboten'], + ['es', 'Prohibido'], + ['zh', '禁止访问'], + ['id', 'Dilarang'], + ['pl', 'Zabroniony'], + ])], + [tkn('Access is forbidden to the requested page'), new Map([ + ['fr', 'Accès interdit à la page demandée'], + ['ru', 'Доступ к странице запрещён'], + ['uk', 'Доступ до сторінки заборонено'], + ['pt', 'É proibido o acesso à página solicitada'], + ['nl', 'Toegang tot de pagina is verboden'], + ['de', 'Der Zugriff auf die angeforderte Seite ist verboten'], + ['es', 'El acceso está prohibido para la página solicitada'], + ['zh', '禁止访问请求的页面'], + ['id', 'Akses dilarang ke halaman yang diminta'], + ['pl', 'Dostęp do żądanej strony jest zabroniony'], + ])], + [tkn('Not Found'), new Map([ + ['fr', 'Introuvable'], + ['ru', 'Страница не найдена'], + ['uk', 'Сторінку не знайдено'], + ['pt', 'Não encontrado'], + ['nl', 'Niet gevonden'], + ['de', 'Nicht gefunden'], + ['es', 'No encontrado'], + ['zh', '未找到'], + ['id', 'Tidak ditemukan'], + ['pl', 'Nie znaleziono'], + ])], + [tkn('The server can not find the requested page'), new Map([ + ['fr', 'Le serveur ne peut trouver la page demandée'], + ['ru', 'Сервер не смог найти запрашиваемую страницу'], + ['uk', 'Сервер не зміг знайти запитану сторінку'], + ['pt', 'O servidor não consegue encontrar a página solicitada'], + ['nl', 'De server kan de pagina niet vinden'], + ['de', 'Der Server kann die angeforderte Seite nicht finden'], + ['es', 'El servidor no puede encontrar la página solicitada'], + ['zh', '服务器找不到请求的页面'], + ['id', 'Server tidak dapat menemukan halaman yang diminta'], + ['pl', 'Serwer nie może znaleźć żądanej strony'], + ])], + [tkn('Method Not Allowed'), new Map([ + ['fr', 'Méthode Non Autorisée'], + ['ru', 'Метод не поддерживается'], + ['uk', 'Неприпустимий метод'], + ['pt', 'Método não permitido'], + ['nl', 'Methode niet toegestaan'], + ['de', 'Methode nicht erlaubt'], + ['es', 'Método no permitido'], + ['zh', '方法不被允许'], + ['id', 'Metode tidak diizinkan'], + ['pl', 'Niedozwolona metoda'], + ])], + [tkn('The method specified in the request is not allowed'), new Map([ + ['fr', 'La méthode spécifiée dans la requête n’est pas autorisée'], + ['ru', 'Указанный в запросе метод не поддерживается'], + ['uk', 'Метод, зазначений у запиті, не підтримується'], + ['pt', 'O método especificado na solicitação não é permitido'], + ['nl', 'De methode in het verzoek is niet toegestaan'], + ['de', 'Die in der Anfrage angegebene Methode ist nicht zulässig'], + ['es', 'El método especificado en la petición no está permitido'], + ['zh', '请求指定的方法不被允许'], + ['id', 'Metode dalam permintaan tidak diizinkan'], + ['pl', 'Metoda określona w żądaniu jest niedozwolona'], + ])], + [tkn('Proxy Authentication Required'), new Map([ + ['fr', 'Authentification proxy requise'], + ['ru', 'Нужна аутентификация прокси'], + ['uk', 'Потрібна ідентифікація проксі'], + ['pt', 'Autenticação de proxy necessária'], + ['nl', 'Authenticatie op de proxyserver verplicht'], + ['de', 'Proxy-Authentifizierung benötigt'], + ['es', 'Autenticación de proxy requerida'], + ['zh', '需要代理服务器身份验证'], + ['id', 'Diperlukan otentikasi proxy'], + ['pl', 'Wymagane uwierzytelnianie proxy'], + ])], + [tkn('You must authenticate with a proxy server before this request can be served'), new Map([ + ['fr', 'Vous devez vous authentifier avec un serveur proxy avant que cette requête puisse être servie'], + ['ru', 'Вы должны быть авторизованы на прокси сервере для обработки этого запроса'], + ['uk', 'Ви повинні увійти до проксі-сервера для обробки цього запиту'], + ['pt', 'Você deve se autenticar com um servidor proxy antes que esta solicitação possa ser atendida'], + ['nl', 'Je moet authenticeren bij een proxyserver voordat dit verzoek uitgevoerd kan worden'], + ['de', 'Sie müssen sich bei einem Proxy-Server authentifizieren, bevor diese Anfrage bedient werden kann'], + ['es', 'Debes autentificarte con un servidor proxy antes de que esta petición pueda ser atendida'], + ['zh', '您必须对代理服务器进行身份验证,然后才能让请求得到处理'], + ['id', 'Anda harus mengautentikasi dengan server proxy sebelum permintaan ini dapat dilayani'], + ['pl', 'Musisz uwierzytelnić się na serwerze proxy, zanim to żądanie będzie mogło zostać obsłużone'], + ])], + [tkn('Request Timeout'), new Map([ + ['fr', 'Requête expiré'], + ['ru', 'Истекло время ожидания'], + ['uk', 'Вичерпано час очікування'], + ['pt', 'Tempo limite de solicitação excedido'], + ['nl', 'Aanvraagtijd verstreken'], + ['de', 'Zeitüberschreitung der Anforderung'], + ['es', 'Tiempo límite de la petición excedido'], + ['zh', '请求超时'], + ['id', 'Meminta batas waktu'], + ['pl', 'Przekroczenie limitu czasu żądania'], + ])], + [tkn('The request took longer than the server was prepared to wait'), new Map([ + ['fr', 'La requête prend plus de temps que prévu'], + ['ru', 'Отправка запроса заняла слишком много времени'], + ['uk', 'Надсилання запиту зайняло надто багато часу'], + ['pt', 'A solicitação demorou mais do que o servidor estava preparado para esperar'], + ['nl', 'Het verzoek duurde langer dan de server wilde wachten'], + ['de', 'Die Anfrage hat länger gedauert, als der Server bereit war zu warten'], + ['es', 'La petición esta tardando más de lo que el servidor estaba preparado para esperar'], + ['zh', '请求用时超过了服务器设置的最长等待时间'], + ['id', 'Permintaan memakan waktu lebih lama dari yang bisa ditunggu oleh server'], + ['pl', 'Żądanie trwało dłużej niż serwer był gotowy czekać'], + ])], + [tkn('Conflict'), new Map([ + ['fr', 'Conflit'], + ['ru', 'Конфликт'], + ['uk', 'Конфлікт'], + ['pt', 'Conflito'], + ['nl', 'Conflict'], + ['de', 'Konflikt'], + ['es', 'Conflicto'], + ['zh', '冲突'], + ['id', 'Konflik'], + ['pl', 'Konflikt'], + ])], + [tkn('The request could not be completed because of a conflict'), new Map([ + ['fr', 'La requête n’a pas pu être complétée à cause d’un conflit'], + ['ru', 'Запрос не может быть обработан из-за конфликта'], + ['uk', 'Запит не може бути оброблений через конфлікт'], + ['pt', 'A solicitação não pôde ser concluída devido a um conflito'], + ['nl', 'Het verzoek kon niet worden verwerkt vanwege een conflict'], + ['de', 'Die Anfrage konnte aufgrund eines Konflikts nicht abgeschlossen werden'], + ['es', 'La petición no ha podido ser completada por un conflicto'], + ['zh', '由于冲突,请求无法完成'], + ['id', 'Permintaan tidak dapat diselesaikan karena adanya konflik'], + ['pl', 'Żądanie nie mogło zostać wykonane z powodu konfliktu'], + ])], + [tkn('Gone'), new Map([ + ['fr', 'Supprimé'], + ['ru', 'Удалено'], + ['uk', 'Вилучений'], + ['pt', 'Removido'], + ['nl', 'Verdwenen'], + ['de', 'Verschwunden'], + ['es', 'Eliminado'], + ['zh', '已移除'], + ['id', 'Menghilang'], + ['pl', 'Usunięto'], + ])], + [tkn('The requested page is no longer available'), new Map([ + ['fr', 'La page demandée n’est plus disponible'], + ['ru', 'Запрошенная страница была удалена'], + ['uk', 'Запитувана сторінка більше не доступна'], + ['pt', 'A página solicitada não está mais disponível'], + ['nl', 'De pagina is niet langer beschikbaar'], + ['de', 'Die angeforderte Seite ist nicht mehr verfügbar'], + ['es', 'La página solicitada no está ya disponible'], + ['zh', '请求的页面不再可用'], + ['id', 'Halaman yang diminta tidak lagi tersedia'], + ['pl', 'Żądana strona nie jest już dostępna'], + ])], + [tkn('Length Required'), new Map([ + ['fr', 'Longueur requise'], + ['ru', 'Необходима длина'], + ['uk', 'Потрібно вказати довжину'], + ['pt', 'Content-Length necessário'], + ['nl', 'Lengte benodigd'], + ['de', 'Länge benötigt'], + ['es', 'Longitud requerida'], + ['zh', '需要长度'], + ['id', 'Panjang yang diperlukan'], + ['pl', 'Wymagana długość'], + ])], + [tkn('The "Content-Length" is not defined. The server will not accept the request without it'), new Map([ + ['fr', 'Le "Content-Length" n’est pas défini. Le serveur ne prendra pas en compte la requête'], + ['ru', 'Заголовок "Content-Length" не был передан. Сервер не может обработать запрос без него'], + ['uk', 'Заголовок "Content-Length" не був переданий. Сервер не може обробити запит без нього'], + ['pt', 'O "Content-Length" não está definido. O servidor não aceitará a solicitação sem ele'], + ['nl', 'De "Content-Length" is niet gespecificeerd. De server accepteert het verzoek niet zonder'], + ['de', 'Die "Content-Length" ist nicht definiert. Ohne sie akzeptiert der Server die Anfrage nicht'], + ['es', 'El "Content-Legth" no eta definido. Este servidor no aceptará la petición sin él'], + ['zh', '未指定Content-Length(内容长度)。服务器将不接受不包含此头信息的请求'], + ['id', '"Content-Length" tidak ditentukan. Server tidak akan menerima permintaan tanpa itu'], + ['pl', 'Wartość "Content-Length" nie jest zdefiniowana. Serwer nie zaakceptuje żądania bez tego parametru'], + ])], + [tkn('Precondition Failed'), new Map([ + ['fr', 'Échec de la condition préalable'], + ['ru', 'Условие ложно'], + ['uk', 'Збій під час обробки попередньої умови'], + ['pt', 'Falha na pré-condição'], + ['nl', 'Niet voldaan aan vooraf gestelde voorwaarde'], + ['de', 'Vorbedingung fehlgeschlagen'], + ['es', 'Precondición fallida'], + ['zh', '前置条件判定失败'], + ['id', 'Prasyarat gagal'], + ['pl', 'Niespełnienie warunku wstępnego'], + ])], + [tkn('The pre condition given in the request evaluated to false by the server'), new Map([ + ['fr', 'La précondition donnée dans la requête a été évaluée comme étant fausse par le serveur'], + ['ru', 'Ни одно из условных полей заголовка запроса не было выполнено'], + ['uk', 'Жодна з передумов запиту не була виконана'], + ['pt', 'A pré-condição dada na solicitação avaliada como falsa pelo servidor'], + ['nl', 'De vooraf gestelde voorwaarde is afgewezen door de server'], + ['de', 'Die in der Anfrage angegebene Vorbedingung wird vom Server als falsch bewertet'], + ['es', 'La precondición ha sido evaluada como negativa para esta petición por el servidor'], + ['zh', '服务器评估请求中给出的前置条件的结果为false(假)'], + ['id', 'Prakondisi gagal'], + ['pl', 'Warunek wstępny podany w żądaniu został oceniony przez serwer jako nieprawidłowy'], + ])], + [tkn('Payload Too Large'), new Map([ + ['fr', 'Charge trop volumineuse'], + ['ru', 'Слишком большой запрос'], + ['uk', 'Занадто великий запит'], + ['pt', 'Payload muito grande'], + ['nl', 'Aanvraag te grood'], + ['de', 'Anfrage zu groß'], + ['es', 'Carga demasiado grande'], + ['zh', '请求体过大'], + ['id', 'Muatan terlalu besar'], + ['pl', 'Żądanie jest zbyt duże'], + ])], + [tkn('The server will not accept the request, because the request entity is too large'), new Map([ + ['fr', 'Le serveur ne prendra pas en compte la requête, car l’entité de la requête est trop volumineuse'], + ['ru', 'Сервер не может обработать запрос, так как он слишком большой'], + ['uk', 'Сервер не може обробити запит, оскільки він занадто великий'], + ['pt', 'O servidor não aceitará a solicitação porque a entidade da solicitação é muito grande'], + ['nl', 'De server accepteert het verzoek niet omdat de aanvraag te groot is'], + ['de', 'Der Server akzeptiert die Anfrage nicht, da die Datenmenge zu groß ist'], + ['es', 'El servidor no aceptará esta petición, porque la carga es demasiado grande'], + ['zh', '请求体过大,服务器将不接受该请求'], + ['id', 'Server tidak akan menerima permintaan, karena entitas permintaan terlalu besar'], + ['pl', 'Serwer nie zaakceptuje żądania, ponieważ żądanie jest zbyt duże'], + ])], + [tkn('Requested Range Not Satisfiable'), new Map([ + ['fr', 'Requête non satisfaisante'], + ['ru', 'Диапазон не достижим'], + ['uk', 'Запитуваний діапазон недосяжний'], + ['pt', 'Intervalo Solicitado Não Satisfatório'], + ['nl', 'Aangevraagd gedeelte niet opvraagbaar'], + ['de', 'Anfrage-Bereich nicht erfüllbar'], + ['es', 'Intervalo solicitado no satisfactorio'], + ['zh', '不满足请求范围'], + ['id', 'Rentang yang diminta tidak dapat dipenuhi'], + ['pl', 'Żądany zakres nie jest satysfakcjonujący'], + ])], + [tkn('The requested byte range is not available and is out of bounds'), new Map([ + ['fr', 'Le byte range demandé n’est pas disponible et est hors des limites'], + ['ru', 'Запрошенный диапазон данных недоступен или вне допустимых пределов'], + ['uk', 'Описаний діапазон даних недоступний або поза допустимими межами'], + ['pt', 'O intervalo de bytes solicitado não está disponível e está fora dos limites'], + ['nl', 'De aangevraagde bytes zijn buiten het limiet'], + ['de', 'Der angefragte Teilbereich der Ressource existiert nicht oder ist ungültig'], + ['es', 'El intervalo de bytes requerido no está disponible o se encuentra fuera de los límites'], + ['zh', '请求的字节范围不可用,超出边界'], + ['id', 'Rentang byte yang diminta tidak tersedia dan di luar batas'], + ['pl', 'Żądany zakres bajtów nie jest dostępny i znajduje się poza zakresem'], + ])], + [tkn("I'm a teapot"), new Map([ + ['fr', 'Je suis une théière'], + ['ru', 'Я чайник'], + ['uk', 'Я чайник'], + ['pt', 'Eu sou um bule'], + ['nl', 'Ik ben een theepot'], + ['de', 'Ich bin eine Teekanne'], + ['es', 'Soy una tetera'], + ['zh', '我是一只茶壶'], + ['id', 'Saya adalah teko'], + ['pl', 'Jestem czajniczkiem'], + ])], + [tkn('Attempt to brew coffee with a teapot is not supported'), new Map([ + ['fr', 'Tenter de préparer du café avec une théière n’est pas pris en charge'], + ['ru', 'Попытка заварить кофе в чайнике обречена на фиаско'], + ['uk', 'Спроба заварити каву в чайнику приречена на фіаско'], + ['pt', 'A tentativa de preparar café com um bule não é suportada'], + ['nl', 'Koffie maken met een theepot is niet ondersteund'], + ['de', 'Der Versuch, Kaffee mit einer Teekanne zuzubereiten, wird nicht unterstützt'], + ['es', 'Intentar hacer un café en una tetera no está soportado'], + ['zh', '用茶壶泡咖啡不受支持'], + ['id', 'Upaya menyeduh kopi dengan teko tidak didukung'], + ['pl', 'Próba zaparzenia kawy za pomocą czajniczka nie jest obsługiwana'], + ])], + [tkn('Too Many Requests'), new Map([ + ['fr', 'Trop de requêtes'], + ['ru', 'Слишком много запросов'], + ['uk', 'Занадто багато запитів'], + ['pt', 'Excesso de solicitações'], + ['nl', 'Te veel requests'], + ['de', 'Zu viele Anfragen'], + ['es', 'Demasiadas peticiones'], + ['zh', '请求过多'], + ['id', 'Terlalu banyak permintaan'], + ['pl', 'Zbyt wiele żądań'], + ])], + [tkn('Too many requests in a given amount of time'), new Map([ + ['fr', 'Trop de requêtes dans un délai donné'], + ['ru', 'Отправлено слишком много запросов за короткое время'], + ['uk', 'Надіслано занадто багато запитів за короткий проміжок час'], + ['pt', 'Excesso de solicitações em um determinado período de tempo'], + ['nl', 'Te veel verzoeken binnen een bepaalde tijd'], + ['de', 'Der Client hat zu viele Anfragen in einem bestimmten Zeitraum gesendet'], + ['es', 'Demasiadas peticiones en un determinado periodo de tiempo'], + ['zh', '在给定的时间内发送了过多请求'], + ['id', 'Terlalu banyak permintaan dalam waktu tertentu'], + ['pl', 'Zbyt wiele żądań w określonym czasie'], + ])], + [tkn('Internal Server Error'), new Map([ + ['fr', 'Erreur interne du serveur'], + ['ru', 'Внутренняя ошибка сервера'], + ['uk', 'Внутрішня помилка сервера'], + ['pt', 'Erro do Servidor Interno'], + ['nl', 'Interne serverfout'], + ['de', 'Interner Server-Fehler'], + ['es', 'Error Interno'], + ['zh', '内部服务器错误'], + ['id', 'Kesalahan server internal'], + ['pl', 'Wewnętrzny błąd serwera'], + ])], + [tkn('The server met an unexpected condition'), new Map([ + ['fr', 'Le serveur a rencontré une condition inattendue'], + ['ru', 'Произошло что-то неожиданное на сервере'], + ['uk', 'На сервері відбулось щось неочікуване'], + ['pt', 'O servidor encontrou uma condição inesperada'], + ['nl', 'De server ondervond een onverwachte conditie'], + ['de', 'Der Server hat einen internen Fehler festgestellt'], + ['es', 'El servidor ha encontrado una condición no esperada'], + ['zh', '服务器遇到了意外情况'], + ['id', 'Server mengalami kondisi yang tidak terduga'], + ['pl', 'Serwer napotkał nieoczekiwany stan'], + ])], + [tkn('Bad Gateway'), new Map([ + ['fr', 'Mauvaise passerelle'], + ['ru', 'Ошибка шлюза'], + ['uk', 'Помилка шлюзу'], + ['pt', 'Gateway inválido'], + ['nl', 'Ongeldige Gateway'], + ['de', 'Fehlerhaftes Gateway'], + ['es', 'Puerta de enlace no valida'], + ['zh', '无效网关'], + ['id', 'Gateway yang buruk'], + ['pl', 'Błąd bramki'], + ])], + [tkn('The server received an invalid response from the upstream server'), new Map([ + ['fr', 'Le serveur a reçu une réponse invalide du serveur distant'], + ['ru', 'Сервер получил некорректный ответ от вышестоящего сервера'], + ['uk', 'Сервер отримав невірну відповідь від попереднього сервера'], + ['pt', 'O servidor recebeu uma resposta inválida do servidor upstream'], + ['nl', 'De server ontving een ongeldig antwoord van een bovenliggende server'], + ['de', 'Der Server hat eine ungültige Antwort vom Upstream-Server erhalten'], + ['es', 'El servidor ha recibido una respuesta no válida del servidor de origen'], + ['zh', '服务器从上游服务器收到了无效的响应'], + ['id', 'Server menerima respons yang tidak valid dari server induk'], + ['pl', 'Serwer otrzymał nieprawidłową odpowiedź od serwera nadrzędnego'], + ])], + [tkn('Service Unavailable'), new Map([ + ['fr', 'Service indisponible'], + ['ru', 'Сервис недоступен'], + ['uk', 'Сервіс недоступний'], + ['pt', 'Serviço não disponível'], + ['nl', 'Dienst niet beschikbaar'], + ['de', 'Dienst nicht verfügbar'], + ['es', 'Servicio no disponible'], + ['zh', '服务不可用'], + ['id', 'Layanan tidak tersedia'], + ['pl', 'Serwis niedostępny'], + ])], + [tkn('The server is temporarily overloading or down'), new Map([ + ['fr', 'Le serveur est temporairement en surcharge ou indisponible'], + ['ru', 'Сервер временно не может обрабатывать запросы по техническим причинам'], + ['uk', 'Сервер тимчасово не може обробляти запити з технічних причин'], + ['pt', 'O servidor está temporariamente sobrecarregado ou inativo'], + ['nl', 'De server is tijdelijk overbelast of niet bereikbaar'], + ['de', 'Der Server ist vorübergehend überlastet oder ausgefallen'], + ['es', 'El servidor está temporalmente sobrecargado o inactivo'], + ['zh', '服务器暂时过载或不可用'], + ['id', 'Server untuk sementara kelebihan beban atau tidak tersedia'], + ['pl', 'Serwer jest tymczasowo przeciążony lub wyłączony'], + ])], + [tkn('Gateway Timeout'), new Map([ + ['fr', 'Expiration Passerelle'], + ['ru', 'Шлюз не отвечает'], + ['uk', 'Шлюз не відповідає'], + ['pt', 'Tempo limite do gateway excedido'], + ['nl', 'Gateway Verlopen'], + ['de', 'Gateway Zeitüberschreitung'], + ['es', 'Tiempo límite de puerta de enlace excedido'], + ['zh', '网关超时'], + ['id', 'Batas waktu gateway'], + ['pl', 'Przekroczenie limitu czasu bramki'], + ])], + [tkn('The gateway has timed out'), new Map([ + ['fr', 'Le temps d’attente de la passerelle est dépassé'], + ['ru', 'Сервер не дождался ответа от вышестоящего сервера'], + ['uk', 'У шлюзу закінчився час очікування'], + ['pt', 'O gateway esgotou o tempo limite'], + ['nl', 'De verbinding naar de bovenliggende server is verlopen'], + ['de', 'Das Zeitlimit für den Verbindungsaufbau mit dem Upstream-Server ist abgelaufen'], + ['es', 'La puerta de enlace ha sobrepasado el tiempo límite'], + ['zh', '网关响应已经超时'], + ['id', 'Sambungan ke server induk telah kedaluwarsa'], + ['pl', 'Bramka przekroczyła limit czasu'], + ])], + [tkn('HTTP Version Not Supported'), new Map([ + ['fr', 'Version HTTP non prise en charge'], + ['ru', 'Версия HTTP не поддерживается'], + ['uk', 'Версія НТТР не підтримується'], + ['pt', 'Versão HTTP não suportada'], + ['nl', 'HTTP-versie wordt niet ondersteunt'], + ['de', 'HTTP-Version wird nicht unterstützt'], + ['es', 'Versión de HTTP no soportada'], + ['zh', 'HTTP版本不受支持'], + ['id', 'Versi HTTP tidak didukung'], + ['pl', 'Wersja HTTP nie jest obsługiwana'], + ])], + [tkn('The server does not support the "http protocol" version'), new Map([ + ['fr', 'Le serveur ne supporte pas la version du protocole HTTP'], + ['ru', 'Сервер не поддерживает запрошенную версию HTTP протокола'], + ['uk', 'Сервер не підтримує запитану версію HTTP-протоколу'], + ['pt', 'O servidor não suporta a versão do protocolo HTTP'], + ['nl', 'De server ondersteunt deze HTTP-versie niet'], + ['de', 'Der Server unterstützt die HTTP-Protokoll-Version nicht'], + ['es', 'El servidor no soporta la versión del protocolo HTTP'], + ['zh', '服务器不支持该HTTP协议版本'], + ['id', 'Server tidak mendukung versi HTTP ini'], + ['pl', 'Serwer nie obsługuje wersji "protokołu http"'], + ])], + [tkn('Host'), new Map([ + ['fr', 'Hôte'], + ['ru', 'Хост'], + ['uk', 'Хост'], + ['pt', 'Hospedeiro'], + ['nl', 'Host'], + ['de', 'Host'], + ['es', 'Host'], + ['zh', '主机'], + ['id', 'Host'], + ['pl', 'Host'], + ])], + [tkn('Original URI'), new Map([ + ['fr', 'URI d’origine'], + ['ru', 'Исходный URI'], + ['uk', 'Вихідний URI'], + ['pt', 'URI original'], + ['nl', 'Originele URI'], + ['de', 'Originale URI'], + ['es', 'URI original'], + ['zh', '原始URI'], + ['id', 'URL asli'], + ['pl', 'Oryginalny URI'], + ])], + [tkn('Forwarded for'), new Map([ + ['fr', 'Transmis pour'], + ['ru', 'Перенаправлен'], + ['uk', 'Перенаправлений'], + ['pt', 'Encaminhado para'], + ['nl', 'Doorgestuurd voor'], + ['de', 'Weitergeleitet für'], + ['es', 'Remitido para'], + ['zh', '转发自'], + ['id', 'Diteruskan untuk'], + ['pl', 'Przekazane do'], + ])], + [tkn('Namespace'), new Map([ + ['fr', 'Espace de noms'], + ['ru', 'Пространство имён'], + ['uk', 'Простір імен'], + ['pt', 'Namespace'], + ['nl', 'Elementnaam'], + ['de', 'Namensraum'], + ['es', 'Namespace'], + ['zh', '命名空间'], + ['id', 'Ruang nama'], + ['pl', 'Przestrzeń nazw'], + ])], + [tkn('Ingress name'), new Map([ + ['fr', 'Nom ingress'], + ['ru', 'Имя Ingress'], + ['uk', "Ім'я входу"], + ['pt', 'Nome Ingress'], + ['nl', 'Ingress naam'], + ['de', 'Ingress Name'], + ['es', 'Nombre Ingress'], + ['zh', '入口名'], + ['id', 'Nama ingress'], + ['pl', 'Nazwa wejścia'], + ])], + [tkn('Service name'), new Map([ + ['fr', 'Nom du service'], + ['ru', 'Имя сервиса'], + ['uk', "Ім'я сервісу"], + ['pt', 'Nome do Serviço'], + ['nl', 'Service naam'], + ['de', 'Service Name'], + ['es', 'Nombre del servicio'], + ['zh', '服务名'], + ['id', 'Nama layanan'], + ['pl', 'Nazwa usługi'], + ])], + [tkn('Service port'), new Map([ + ['fr', 'Port du service'], + ['ru', 'Порт сервиса'], + ['uk', 'Порт сервісу'], + ['pt', 'Porta do serviço'], + ['nl', 'Service poort'], + ['de', 'Service Port'], + ['es', 'Puerto del servicio'], + ['zh', '服务端口'], + ['id', 'Port layanan'], + ['pl', 'Port usługi'], + ])], + [tkn('Request ID'), new Map([ + ['fr', 'Identifiant de la requête'], + ['ru', 'ID запроса'], + ['uk', 'ID запиту'], + ['pt', 'ID da solicitação'], + ['nl', 'ID van het verzoek'], + ['de', 'Anfrage ID'], + ['es', 'ID de la petición'], + ['zh', '请求ID'], + ['id', 'ID permintaan'], + ['pl', 'Identyfikator żądania'], + ])], + [tkn('Timestamp'), new Map([ + ['fr', 'Horodatage'], + ['ru', 'Временная метка'], + ['uk', 'Мітка часу'], + ['pt', 'Timestamp'], + ['nl', 'Tijdstempel'], + ['de', 'Zeitstempel'], + ['es', 'Timestamp'], + ['zh', '时间戳'], + ['id', 'Cap waktu'], + ['pl', 'Sygnatura czasowa'], + ])], + [tkn('client-side error'), new Map([ + ['fr', 'Erreur Client'], + ['ru', 'ошибка на стороне клиента'], + ['uk', 'помилка на стороні клієнта'], + ['pt', 'erro do lado do cliente'], + ['nl', 'fout aan de gebruikerskant'], + ['de', 'Clientseitiger Fehler'], + ['es', 'Error del lado del cliente'], + ['zh', '客户端错误'], + ['id', 'Kesalahan sisi klien'], + ['pl', 'błąd po stronie klienta'], + ])], + [tkn('server-side error'), new Map([ + ['fr', 'Erreur Serveur'], + ['ru', 'ошибка на стороне сервера'], + ['uk', 'помилка на стороні сервера'], + ['pt', 'erro do lado do servidor'], + ['nl', 'fout aan de serverkant'], + ['de', 'Serverseitiger Fehler'], + ['es', 'Error del lado del servidor'], + ['zh', '服务端错误'], + ['id', 'Kesalahan sisi server'], + ['pl', 'błąd po stronie serwera'], + ])], + [tkn('Your Client'), new Map([ + ['fr', 'Votre Client'], + ['ru', 'Ваш Браузер'], + ['uk', 'Ваш Браузер'], + ['pt', 'Seu Cliente'], + ['nl', 'Jouw Client'], + ['de', 'Ihr Client'], + ['es', 'Tu Cliente'], + ['zh', '您的客户端'], + ['id', 'Klien Anda'], + ['pl', 'Klient'], + ])], + [tkn('Network'), new Map([ + ['fr', 'Réseau'], + ['ru', 'Сеть'], + ['uk', 'Мережа'], + ['pt', 'Rede'], + ['nl', 'Netwerk'], + ['de', 'Netzwerk'], + ['es', 'Red'], + ['zh', '网络'], + ['id', 'Jaringan'], + ['pl', 'Sieć'], + ])], + [tkn('Web Server'), new Map([ + ['fr', 'Serveur Web'], + ['ru', 'Web Сервер'], + ['uk', 'Web-сервер'], + ['pt', 'Servidor web'], + ['nl', 'Web Server'], + ['de', 'Webserver'], + ['es', 'Servidor Web'], + ['zh', 'Web服务器'], + ['id', 'Server web'], + ['pl', 'Serwer WWW'], + ])], + [tkn('What happened?'), new Map([ + ['fr', 'Que s’est-il passé ?'], + ['ru', 'Что произошло?'], + ['uk', 'Що сталося?'], + ['pt', 'O que aconteceu?'], + ['nl', 'Wat is er gebeurd?'], + ['de', 'Was ist passiert?'], + ['es', '¿Que ha pasado?'], + ['zh', '发生了什么?'], + ['id', 'Apa yang terjadi?'], + ['pl', 'Co się stało?'], + ])], + [tkn('What can I do?'), new Map([ + ['fr', 'Que puis-je faire ?'], + ['ru', 'Что можно сделать?'], + ['uk', 'Що можна зробити?'], + ['pt', 'O que eu posso fazer?'], + ['nl', 'Wat kan ik doen?'], + ['de', 'Was kann ich machen?'], + ['es', '¿Que puedo hacer?'], + ['zh', '我能做什么?'], + ['id', 'Apa yang bisa saya lakukan?'], + ['pl', 'Co mogę zrobić?'], + ])], + [tkn('Please try again in a few minutes'), new Map([ + ['fr', 'Veuillez réessayer dans quelques minutes'], + ['ru', 'Пожалуйста, попробуйте повторить запрос ещё раз чуть позже'], + ['uk', 'Будь ласка, спробуйте повторити запит ще раз трохи пізніше'], + ['pt', 'Por favor, tente novamente em alguns minutos'], + ['nl', 'Probeer het alstublieft opnieuw over een paar minuten'], + ['de', 'Bitte versuchen Sie es in ein paar Minuten erneut'], + ['es', 'Por favor, intente nuevamente en unos minutos'], + ['zh', '请在几分钟后重试'], + ['id', 'Silakan coba lagi dalam beberapa menit'], + ['pl', 'Spróbuj ponownie za kilka minut'], + ])], + [tkn('Working'), new Map([ + ['fr', 'Opérationnel'], + ['ru', 'Работает'], + ['uk', 'Працює'], + ['pt', 'Funcionando'], + ['nl', 'Functioneel'], + ['de', 'Funktioniert'], + ['es', 'Funcionando'], + ['zh', '正常运行'], + ['id', 'Fungsi'], + ['pl', 'Działa'], + ])], + [tkn('Unknown'), new Map([ + ['fr', 'Inconnu'], + ['ru', 'Неизвестно'], + ['uk', 'Невідомо'], + ['pt', 'Desconhecido'], + ['nl', 'Onbekend'], + ['de', 'Unbekannt'], + ['es', 'Desconocido'], + ['zh', '未知'], + ['id', 'Tidak diketahui'], + ['pl', 'Nieznany'], + ])], + [tkn('Please try to change the request method, headers, payload, or URL'), new Map([ + ['fr', 'Veuillez essayer de changer la méthode de requête, les en-têtes, le contenu ou l’URL'], + ['ru', 'Пожалуйста, попробуйте изменить метод запроса, заголовки, его содержимое или URL'], + ['uk', 'Будь ласка, спробуйте змінити метод запиту, заголовки, його вміст або URL-адресу'], + ['pt', 'Tente alterar o método de solicitação, cabeçalhos, payload ou URL'], + ['nl', 'Probeer het opnieuw met een andere methode, headers, payload of URL'], + ['de', 'Bitte versuchen Sie, die Anfragemethode, Header, Payload oder URL zu ändern'], + ['es', 'Por favor intente cambiar el método de la petición, cabeceras, carga o URL'], + ['zh', '请尝试更改请求方法、标头、有效负载或URL'], + ['id', 'Coba lagi dengan metode, header, muatan, atau URL yang berbeda'], + ['pl', 'Spróbuj zmienić metodę żądania, nagłówki, żądanie lub adres URL'], + ])], + [tkn('Please check your authorization data'), new Map([ + ['fr', 'Veuillez vérifier vos données d’autorisation'], + ['ru', 'Пожалуйста, проверьте данные авторизации'], + ['uk', 'Будь ласка, перевірте дані авторизації'], + ['pt', 'Verifique seus dados de autorização'], + ['nl', 'Controleer de authenticatiegegevens'], + ['de', 'Bitte überprüfen Sie Ihre Zugangsdaten'], + ['es', 'Verifique sus datos de autorización'], + ['zh', '请检查您的授权数据'], + ['id', 'Memeriksa detail autentikasi'], + ['pl', 'Sprawdź swoje dane autoryzacyjne'], + ])], + [tkn('Please double-check the URL and try again'), new Map([ + ['fr', 'Veuillez vérifier l’URL et réessayer'], + ['ru', 'Пожалуйста, дважды проверьте URL и попробуйте снова'], + ['uk', 'Будь ласка, двічі перевірте URL-адресу і спробуйте знову'], + ['pt', 'Verifique novamente o URL e tente novamente'], + ['nl', 'Controleer de URL en probeer het opnieuw'], + ['de', 'Bitte überprüfen Sie die URL und versuchen Sie es erneut'], + ['es', 'Verifique de nuevo la URL y vuelva a probar'], + ['zh', '请再次检查URL并重试'], + ['id', 'Periksa URL dan coba lagi'], + ['pl', 'Sprawdź adres URL i spróbuj ponownie'], + ])], + ])); - 'Your Client': { - fr: 'Votre Client', - ru: 'Ваш Браузер', - uk: 'Ваш Браузер', - pt: 'Seu Cliente', - nl: 'Jouw Client', - de: 'Ihr Client', - es: 'Tu Cliente', - zh: '您的客户端', - id: 'Klien Anda', - pl: 'Klient', - }, - 'Network': { - fr: 'Réseau', - ru: 'Сеть', - uk: 'Мережа', - pt: 'Rede', - nl: 'Netwerk', - de: 'Netzwerk', - es: 'Red', - zh: '网络', - id: 'Jaringan', - pl: 'Sieć', - }, - 'Web Server': { - fr: 'Serveur Web', - ru: 'Web Сервер', - uk: 'Web-сервер', - pt: 'Servidor web', - nl: 'Web Server', - de: 'Webserver', - es: 'Servidor Web', - zh: 'Web服务器', - id: 'Server web', - pl: 'Serwer WWW', - }, - 'What happened?': { - fr: 'Que s’est-il passé ?', - ru: 'Что произошло?', - uk: 'Що сталося?', - pt: 'O que aconteceu?', - nl: 'Wat is er gebeurd?', - de: 'Was ist passiert?', - es: '¿Que ha pasado?', - zh: '发生了什么?', - id: 'Apa yang terjadi?', - pl: 'Co się stało?', - }, - 'What can i do?': { - fr: 'Que puis-je faire ?', - ru: 'Что можно сделать?', - uk: 'Що можна зробити?', - pt: 'O que eu posso fazer?', - nl: 'Wat kan ik doen?', - de: 'Was kann ich machen?', - es: '¿Que puedo hacer?', - zh: '我能做什么?', - id: 'Apa yang bisa saya lakukan?', - pl: 'Co mogę zrobić?', - }, - 'Please try again in a few minutes': { - fr: 'Veuillez réessayer dans quelques minutes', - ru: 'Пожалуйста, попробуйте повторить запрос ещё раз чуть позже', - uk: 'Будь ласка, спробуйте повторити запит ще раз трохи пізніше', - pt: 'Por favor, tente novamente em alguns minutos', - nl: 'Probeer het alstublieft opnieuw over een paar minuten', - de: 'Bitte versuchen Sie es in ein paar Minuten erneut', - es: 'Por favor, intente nuevamente en unos minutos', - zh: '请在几分钟后重试', - id: 'Silakan coba lagi dalam beberapa menit', - pl: 'Spróbuj ponownie za kilka minut', - }, - 'Working': { - fr: 'Opérationnel', - ru: 'Работает', - uk: 'Працює', - pt: 'Funcionando', - nl: 'Functioneel', - de: 'Funktioniert', - es: 'Funcionando', - zh: '正常运行', - id: 'Fungsi', - pl: 'Działa', - }, - 'Unknown': { - fr: 'Inconnu', - ru: 'Неизвестно', - uk: 'Невідомо', - pt: 'Desconhecido', - nl: 'Onbekend', - de: 'Unbekannt', - es: 'Desconocido', - zh: '未知', - id: 'Tidak diketahui', - pl: 'Nieznany', - }, - 'Please try to change the request method, headers, payload, or URL': { - fr: 'Veuillez essayer de changer la méthode de requête, les en-têtes, le contenu ou l’URL', - ru: 'Пожалуйста, попробуйте изменить метод запроса, заголовки, его содержимое или URL', - uk: 'Будь ласка, спробуйте змінити метод запиту, заголовки, його вміст або URL-адресу', - pt: 'Tente alterar o método de solicitação, cabeçalhos, payload ou URL', - nl: 'Probeer het opnieuw met een andere methode, headers, payload of URL', - de: 'Bitte versuchen Sie, die Anfragemethode, Header, Payload oder URL zu ändern', - es: 'Por favor intente cambiar el método de la petición, cabeceras, carga o URL', - zh: '请尝试更改请求方法、标头、有效负载或URL', - id: 'Coba lagi dengan metode, header, muatan, atau URL yang berbeda', - pl: 'Spróbuj zmienić metodę żądania, nagłówki, żądanie lub adres URL', - }, - 'Please check your authorization data': { - fr: 'Veuillez vérifier vos données d’autorisation', - ru: 'Пожалуйста, проверьте данные авторизации', - uk: 'Будь ласка, перевірте дані авторизації', - pt: 'Verifique seus dados de autorização', - nl: 'Controleer de authenticatiegegevens', - de: 'Bitte überprüfen Sie Ihre Zugangsdaten', - es: 'Verifique sus datos de autorización', - zh: '请检查您的授权数据', - id: 'Memeriksa detail autentikasi', - pl: 'Sprawdź swoje dane autoryzacyjne', - }, - 'Please double-check the URL and try again': { - fr: 'Veuillez vérifier l’URL et réessayer', - ru: 'Пожалуйста, дважды проверьте URL и попробуйте снова', - uk: 'Будь ласка, двічі перевірте URL-адресу і спробуйте знову', - pt: 'Verifique novamente o URL e tente novamente', - nl: 'Controleer de URL en probeer het opnieuw', - de: 'Bitte überprüfen Sie die URL und versuchen Sie es erneut', - es: 'Verifique de nuevo la URL y vuelva a probar', - zh: '请再次检查URL并重试', - id: 'Periksa URL dan coba lagi', - pl: 'Sprawdź adres URL i spróbuj ponownie', - }, - }; + // detect browser locale (take only 2 first symbols) + let activeLocale = navigator.language.substring(0, 2).toLowerCase(); - /** - * @param {string} token - * @return {string} - */ - const serializeToken = function (token) { - return token.toLowerCase().replaceAll(/[^a-z0-9]/g, ''); - }; + // noinspection JSUnusedGlobalSymbols + /** + * @param {string} locale + * @return {void} + */ + this.setLocale = function (locale) { + activeLocale = locale.toLowerCase(); + } - // normalize the data keys - for (const key in data) { - Object.defineProperty(data, serializeToken(key), Object.getOwnPropertyDescriptor(data, key)); - delete data[key]; + /** + * @param {string} token + * @param {string?} def + * @return {string|undefined} + */ + this.translate = function (token, def) { + const t = tkn(token); + + if (activeLocale === 'en' && Object.prototype.hasOwnProperty.call(data, t)) { + return token; + } + + if (data.has(t) && data.get(t).has(activeLocale)) { + return data.get(t).get(activeLocale); + } + + return def; + }; + + /** + * Localize all elements with the HTML attribute `data-l10n`. + * The attribute value is used as a token to translate. + * + * @return {void} + */ + this.localizeDocument = function () { + if (activeLocale === 'en') { + return; // no need to translate + } + + const l10nAttr = 'data-l10n'; // using this attribute we understand that this element should be localized + const l10nOriginalTextAttr = 'data-l10n-original'; // to keep the original text + + // loop through all elements with the `data-l10n` attribute + Array.prototype.forEach.call(document.querySelectorAll('[' + l10nAttr + ']'), ($el) => { + if (!$el.hasAttribute(l10nAttr)) { + return; // skip elements without the `data-l10n` attribute } - // detect browser locale (take only 2 first symbols) - let activeLocale = navigator.language.substring(0, 2).toLowerCase(); - - /** - * @param {string} locale - */ - this.setLocale = function (locale) { - activeLocale = locale.toLowerCase(); + // store the original text if not already stored + if (!$el.hasAttribute(l10nOriginalTextAttr)) { + $el.setAttribute(l10nOriginalTextAttr, $el.innerText); + } else { + $el.innerText = $el.getAttribute(l10nOriginalTextAttr); // restore the original text } - /** - * @param {string} token - * @param {string|undefined?} def - */ - this.translate = function (token, def) { - const t = serializeToken(token); + const attr = $el.getAttribute(l10nAttr).trim(); // get the `data-l10n` attribute value + const token = attr ? attr : $el.innerText.trim(); // use the attribute value as a token, or the element text + const localized = this.translate(token); // translate the token - if (activeLocale === 'en' && Object.prototype.hasOwnProperty.call(data, t)) { - return token - } - - if (Object.prototype.hasOwnProperty.call(data, t) && Object.prototype.hasOwnProperty.call(data[t], activeLocale)) { - return data[t][activeLocale]; - } - - return def; - }; - - /** - * Localize all elements with HTML attribute `data-l10n`. - */ - this.localizeDocument = function () { - const dataAttributeName = 'data-l10n'; - - Array.prototype.forEach.call(document.querySelectorAll('[' + dataAttributeName + ']'), ($el) => { - const attr = $el.getAttribute(dataAttributeName).trim(), - token = attr.length > 0 ? attr : $el.innerText.trim(), - localized = this.translate(token, undefined); - - if (attr.length === 0) { - $el.setAttribute(dataAttributeName, token); - } - - if (localized !== undefined) { - $el.innerText = localized; - } else { - console.debug(`Unsupported l10n token detected: "${token}" (locale "${activeLocale}")`, $el); - } - }); - }; - }, - writable: false, - enumerable: false, + if (localized) { + $el.innerText = localized; // set the translated text + } else { + console.debug(`Unsupported l10n token detected: "${token}" (locale "${activeLocale}")`, $el); + } + }); + }; + }, + writable: false, + enumerable: false, }); window.l10n.localizeDocument(); diff --git a/l10n/playground.html b/l10n/playground.html new file mode 100644 index 0000000..5d0dfb6 --- /dev/null +++ b/l10n/playground.html @@ -0,0 +1,138 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>L10n playground</title> + <style> + :root { + --color-bg-primary: #fff; + --color-text-primary: #0e0620; + --color-ui-bg-primary: #0e0620; + --color-ui-bg-inverted: #fff; + } + + @media (prefers-color-scheme: dark) { + :root { + --color-bg-primary: #212121; + --color-text-primary: #fafafa; + --color-ui-bg-primary: #fafafa; + --color-ui-bg-inverted: #212121; + } + } + + html, body { + margin: 0 auto; + padding: 0; + font-family: Arial, sans-serif; + max-width: 1200px; + min-width: 400px; + background-color: var(--color-bg-primary); + color: var(--color-text-primary); + } + + #lang-switch { + list-style-type: none; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + flex-grow: 4; + gap: 1em; + padding: 2em 0; + + button { + background-color: var(--color-bg-primary); + color: var(--color-text-primary); + border: 1px solid var(--color-text-primary); + padding: 0.5em 1em; + cursor: pointer; + font-size: 1.2em; + font-weight: bold; + border-radius: 1em 0 1em 0; + transition: background-color 0.3s, color 0.3s; + + &:hover { + background-color: var(--color-ui-bg-primary); + color: var(--color-ui-bg-inverted); + } + } + } + + #tokens-list { + list-style-type: none; + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 1em; + padding: 0 1em; + + li { + padding: 0.5em 1em; + font-size: 1.2em; + + &::first-letter { + font-weight: bold; + } + } + } + </style> +</head> +<body> +<ul id="lang-switch"></ul> +<ul id="tokens-list"></ul> +<script type="module"> + const $tokensList = document.getElementById('tokens-list'); + + [ + 'Error', 'Good luck', 'UH OH', 'Request details', 'Double-check the URL', 'Alternatively, go back', 'Host', + "Here's what might have happened", 'You may have mistyped the URL', 'The site was moved', 'It was never here', + 'Bad Request', 'The server did not understand the request', 'Unauthorized', 'Method Not Allowed', 'Bad Gateway', + 'The requested page needs a username and a password', 'Forbidden', 'Access is forbidden to the requested page', + 'Not Found', 'The server can not find the requested page', 'The method specified in the request is not allowed', + 'Proxy Authentication Required', 'You must authenticate with a proxy server before this request can be served', + 'Request Timeout', 'The request took longer than the server was prepared to wait', 'Conflict', "I'm a teapot", + 'The request could not be completed because of a conflict', 'Gone', 'The requested page is no longer available', + 'Length Required', 'The "Content-Length" is not defined. The server will not accept the request without it', + 'Precondition Failed', 'The pre condition given in the request evaluated to false by the server', 'Namespace', + 'Payload Too Large', 'The server will not accept the request, because the request entity is too large', + 'Requested Range Not Satisfiable', 'The requested byte range is not available and is out of bounds', + 'Attempt to brew coffee with a teapot is not supported', 'Too Many Requests', 'Gateway Timeout', 'Service port', + 'Too many requests in a given amount of time', 'Internal Server Error', 'The server met an unexpected condition', + 'The server received an invalid response from the upstream server', 'Service Unavailable', 'Service name', + 'The server is temporarily overloading or down', 'The gateway has timed out', 'HTTP Version Not Supported', + 'The server does not support the "http protocol" version', 'Original URI', 'Forwarded for', 'Ingress name', + 'Request ID', 'Timestamp', 'client-side error', 'server-side error', 'Your Client', 'Network', 'Web Server', + 'What happened?', 'What can i do?', 'Please try again in a few minutes', 'Working', 'Unknown', + 'Please try to change the request method, headers, payload, or URL', 'Please check your authorization data', + 'Please double-check the URL and try again', + ].forEach((token) => { + const $li = document.createElement('li'); + + $li.textContent = token; + $li.setAttribute('data-l10n', ''); + $li.title = token; + + $tokensList.appendChild($li); + }); + + const $langSwitch = document.getElementById('lang-switch'); + + ['fr', 'ru', 'uk', 'pt', 'nl', 'de', 'es', 'zh', 'id', 'pl'].forEach((lang) => { + // ^^^ add your newly added locale here + const $li = document.createElement('li'); + const $btn = document.createElement('button'); + + $btn.textContent = lang; + $btn.addEventListener('click', () => { + window.l10n.setLocale(lang); + window.l10n.localizeDocument(); + }); + + $li.appendChild($btn); + $langSwitch.appendChild($li); + }); +</script> +<script src="l10n.js" defer async></script> +</body> +</html> diff --git a/l10n/readme.md b/l10n/readme.md index 8515bac..baa522e 100644 --- a/l10n/readme.md +++ b/l10n/readme.md @@ -1,15 +1,22 @@ # 🔤 Localization -[](https://www.jsdelivr.com/package/gh/tarampampam/error-pages) +This directory contains the file [l10n.js](l10n.js) for localizing error pages. Once the error page is loaded, +this script runs and translates the page content to the user's locale. -This directory contains file [l10n.js](l10n.js) for the error pages localization. The working logic is very simple - pages load this script using [jsdelivr.com](https://www.jsdelivr.com/) as a CDN for [versioned content from the GitHub repository](https://www.jsdelivr.com/features#gh), and it translates tag content with the special HTML attribute `data-l10n`. +> [!NOTE] +> In version `2.*`, the working logic was simpler: error pages loaded this script using +> [jsdelivr.com](https://www.jsdelivr.com/) as a CDN for +> [versioned content from the GitHub repository](https://www.jsdelivr.com/features#gh), and it translated +> tag content with the special HTML attribute `data-l10n`. -By default, pages markup contains strings in English (`en` locale). If you want to localize the error pages on the different locales, you should: +By default, the error page markup contains strings in English (`en` locale). To localize the error pages to +different locales, please follow these steps: -- Find your locale name on [this page](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (column `639-1`) -- Make a fork of this repository -- Edit file [l10n.js](l10n.js) in `data` section (append new localized strings) using locale name from the step 1 -- Make a PR with your changes +1. Find your locale name on [this page](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (column `Set 1` or `ISO 639-1:2002`) +2. Fork this repository +3. Edit the file [l10n.js](l10n.js) in the `data` map (append new localized strings) using the locale name from step 1 +4. Please add your locale to the [playground.html](playground.html) file to test the localization +5. Make a PR with your changes ## 👍 Translators diff --git a/templates/embed.go b/templates/embed.go index 64b2195..58a834c 100644 --- a/templates/embed.go +++ b/templates/embed.go @@ -10,9 +10,10 @@ import ( //go:embed *.html var content embed.FS -func BuiltIn() map[string]string { // error check is covered by unit tests +// BuiltIn returns a map of built-in templates. The key is the template name and the value is the template content. +func BuiltIn() map[string]string { var ( - list, _ = fs.ReadDir(content, ".") + list, _ = fs.ReadDir(content, ".") // error check is covered by unit tests result = make(map[string]string, len(list)) ) diff --git a/templates/ghost.html b/templates/ghost.html new file mode 100644 index 0000000..f93d278 --- /dev/null +++ b/templates/ghost.html @@ -0,0 +1,118 @@ +<!DOCTYPE html> +<!-- + Error {{ code }}: {{ message }} + Description: {{ description }} +--> +<html lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta name="robots" content="noindex, nofollow" /> + <title>{{ code }}: {{ message }}</title> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <link rel="preconnect" href="https://fonts.bunny.net" crossorigin> + <link rel="dns-prefetch" href="https://fonts.bunny.net"> + <link href="https://fonts.bunny.net/css2?family=Open+Sans:wght@400;700&display=swap" rel="stylesheet"> + <style> + html,body {background-color:#1a1a1a;color:#fff;font-family:'Open Sans',sans-serif;height:100vh;margin:0;font-size:0} + .container {height:100vh;align-items:center;display:flex;justify-content:center;position:relative} + .wrap {text-align:center} + .ghost {animation:float 3s ease-out infinite} + @keyframes float { 50% {transform:translate(0,20px)}} + .shadowFrame {width:130px;margin: 10px auto 0 auto} + .shadow {animation:shrink 3s ease-out infinite;transform-origin:center center} + @keyframes shrink {0%{width:90%;margin:0 5%} 50% {width:60%;margin:0 18%} 100% {width:90%;margin:0 5%}} + h3 {font-size:17px;text-transform: uppercase;margin:0.3em auto} + .description {font-size:13px;color:#aaa} + /* {{ if show_details }} */ + .details {color:#999;width:100%} + .details table {width:100%} + .details td {white-space:nowrap;font-size:11px} + .details .name {text-align:right;padding-right:.6em;width:50%} + .details .value {text-align:left;padding-left:.6em;font-family:'Lucida Console','Courier New',monospace} + /* {{ end }} */ + </style> +</head> +<body> +<div class="container"> + <div class="wrap"> + <svg class="ghost" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="127.433px" height="132.743px" viewBox="0 0 127.433 132.743" xml:space="preserve"> + <path fill="#FFF6F4" d="M116.223,125.064c1.032-1.183,1.323-2.73,1.391-3.747V54.76c0,0-4.625-34.875-36.125-44.375 s-66,6.625-72.125,44l-0.781,63.219c0.062,4.197,1.105,6.177,1.808,7.006c1.94,1.811,5.408,3.465,10.099-0.6 c7.5-6.5,8.375-10,12.75-6.875s5.875,9.75,13.625,9.25s12.75-9,13.75-9.625s4.375-1.875,7,1.25s5.375,8.25,12.875,7.875 s12.625-8.375,12.625-8.375s2.25-3.875,7.25,0.375s7.625,9.75,14.375,8.125C114.739,126.01,115.412,125.902,116.223,125.064z"></path> + <circle fill="#1a1a1a" cx="86.238" cy="57.885" r="6.667"></circle> + <circle fill="#1a1a1a" cx="40.072" cy="57.885" r="6.667"></circle> + <path fill="#1a1a1a" d="M71.916,62.782c0.05-1.108-0.809-2.046-1.917-2.095c-0.673-0.03-1.28,0.279-1.667,0.771 c-0.758,0.766-2.483,2.235-4.696,2.358c-1.696,0.094-3.438-0.625-5.191-2.137c-0.003-0.003-0.007-0.006-0.011-0.009l0.002,0.005 c-0.332-0.294-0.757-0.488-1.235-0.509c-1.108-0.049-2.046,0.809-2.095,1.917c-0.032,0.724,0.327,1.37,0.887,1.749 c-0.001,0-0.002-0.001-0.003-0.001c2.221,1.871,4.536,2.88,6.912,2.986c0.333,0.014,0.67,0.012,1.007-0.01 c3.163-0.191,5.572-1.942,6.888-3.166l0.452-0.453c0.021-0.019,0.04-0.041,0.06-0.061l0.034-0.034 c-0.007,0.007-0.015,0.014-0.021,0.02C71.666,63.771,71.892,63.307,71.916,62.782z"></path> + <circle fill="#FCEFED" stroke="#FEEBE6" stroke-miterlimit="10" cx="18.614" cy="99.426" r="3.292"></circle> + <circle fill="#FCEFED" stroke="#FEEBE6" stroke-miterlimit="10" cx="95.364" cy="28.676" r="3.291"></circle> + <circle fill="#FCEFED" stroke="#FEEBE6" stroke-miterlimit="10" cx="24.739" cy="93.551" r="2.667"></circle> + <circle fill="#FCEFED" stroke="#FEEBE6" stroke-miterlimit="10" cx="101.489" cy="33.051" r="2.666"></circle> + <circle fill="#FCEFED" stroke="#FEEBE6" stroke-miterlimit="10" cx="18.738" cy="87.717" r="2.833"></circle> + <path fill="#FCEFED" stroke="#FEEBE6" stroke-miterlimit="10" d="M116.279,55.814c-0.021-0.286-2.323-28.744-30.221-41.012 c-7.806-3.433-15.777-5.173-23.691-5.173c-16.889,0-30.283,7.783-37.187,15.067c-9.229,9.736-13.84,26.712-14.191,30.259 l-0.748,62.332c0.149,2.133,1.389,6.167,5.019,6.167c1.891,0,4.074-1.083,6.672-3.311c4.96-4.251,7.424-6.295,9.226-6.295 c1.339,0,2.712,1.213,5.102,3.762c4.121,4.396,7.461,6.355,10.833,6.355c2.713,0,5.311-1.296,7.942-3.962 c3.104-3.145,5.701-5.239,8.285-5.239c2.116,0,4.441,1.421,7.317,4.473c2.638,2.8,5.674,4.219,9.022,4.219 c4.835,0,8.991-2.959,11.27-5.728l0.086-0.104c1.809-2.2,3.237-3.938,5.312-3.938c2.208,0,5.271,1.942,9.359,5.936 c0.54,0.743,3.552,4.674,6.86,4.674c1.37,0,2.559-0.65,3.531-1.932l0.203-0.268L116.279,55.814z M114.281,121.405 c-0.526,0.599-1.096,0.891-1.734,0.891c-2.053,0-4.51-2.82-5.283-3.907l-0.116-0.136c-4.638-4.541-7.975-6.566-10.82-6.566 c-3.021,0-4.884,2.267-6.857,4.667l-0.086,0.104c-1.896,2.307-5.582,4.999-9.725,4.999c-2.775,0-5.322-1.208-7.567-3.59 c-3.325-3.528-6.03-5.102-8.772-5.102c-3.278,0-6.251,2.332-9.708,5.835c-2.236,2.265-4.368,3.366-6.518,3.366 c-2.772,0-5.664-1.765-9.374-5.723c-2.488-2.654-4.29-4.395-6.561-4.395c-2.515,0-5.045,2.077-10.527,6.777 c-2.727,2.337-4.426,2.828-5.37,2.828c-2.662,0-3.017-4.225-3.021-4.225l0.745-62.163c0.332-3.321,4.767-19.625,13.647-28.995 c3.893-4.106,10.387-8.632,18.602-11.504c-0.458,0.503-0.744,1.165-0.744,1.898c0,1.565,1.269,2.833,2.833,2.833 c1.564,0,2.833-1.269,2.833-2.833c0-1.355-0.954-2.485-2.226-2.764c4.419-1.285,9.269-2.074,14.437-2.074 c7.636,0,15.336,1.684,22.887,5.004c26.766,11.771,29.011,39.047,29.027,39.251V121.405z"></path> + </svg> + <p class="shadowFrame"> + <svg class="shadow" xmlns="http://www.w3.org/2000/svg" x="61px" y="20px" width="122.436px" height="39.744px" viewBox="0 0 122.436 39.744" xml:space="preserve"> + <ellipse fill="#262626" cx="61.128" cy="19.872" rx="49.25" ry="8.916"></ellipse> + </svg> + </p> + <h3><span data-l10n>Error</span> {{ code }}</h3> + <p class="description" data-l10n>{{ description }}</p> + {{ if show_details }} + <div class="details"> + <table> + {{- if host }}<tr> + <td class="name" data-l10n>Host</td> + <td class="value">{{ host }}</td> + </tr>{{ end -}} + {{- if original_uri }}<tr> + <td class="name" data-l10n>Original URI</td> + <td class="value">{{ original_uri }}</td> + </tr>{{ end -}} + {{- if forwarded_for }}<tr> + <td class="name" data-l10n>Forwarded for</td> + <td class="value">{{ forwarded_for }}</td> + </tr>{{ end -}} + {{- if namespace }}<tr> + <td class="name" data-l10n>Namespace</td> + <td class="value">{{ namespace }}</td> + </tr>{{ end -}} + {{- if ingress_name }}<tr> + <td class="name" data-l10n>Ingress name</td> + <td class="value">{{ ingress_name }}</td> + </tr>{{ end -}} + {{- if service_name }}<tr> + <td class="name" data-l10n>Service name</td> + <td class="value">{{ service_name }}</td> + </tr>{{ end -}} + {{- if service_port }}<tr> + <td class="name" data-l10n>Service port</td> + <td class="value">{{ service_port }}</td> + </tr>{{ end -}} + {{- if request_id }}<tr> + <td class="name" data-l10n>Request ID</td> + <td class="value">{{ request_id }}</td> + </tr>{{ end -}} + <tr> + <td class="name" data-l10n>Timestamp</td> + <td class="value">{{ now.Unix }}</td> + </tr> + </table> + </div> + {{ end }} + </div> +</div> +<script> + // {{ if l10n_enabled }} + if (navigator.language.substring(0, 2).toLowerCase() !== 'en') { + ((s, p) => { // localize the page (details here - https://github.com/tarampampam/error-pages/tree/master/l10n) + s.src = 'https://cdn.jsdelivr.net/gh/tarampampam/error-pages@2/l10n/l10n.min.js'; // '../l10n/l10n.js'; + s.async = s.defer = true; + s.addEventListener('load', () => p.removeChild(s)); + p.appendChild(s); + })(document.createElement('script'), document.body); + } + // {{ end }} +</script> +</body> +<!-- + Error {{ code }}: {{ message }} + Description: {{ description }} +--> +</html> diff --git a/templates/template-1.html b/templates/template-1.html deleted file mode 100644 index 19a58fe..0000000 --- a/templates/template-1.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <meta charset="UTF-8"> - <title>Template 1</title> -</head> -<body> - -</body> -</html> diff --git a/templates/template-2.html b/templates/template-2.html deleted file mode 100644 index e6bab8e..0000000 --- a/templates/template-2.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <meta charset="UTF-8"> - <title>Template 2</title> -</head> -<body> - -</body> -</html>