diff --git a/.prettierignore b/.prettierignore index a680367..a259ed1 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,2 @@ .next +public/local-data/* \ No newline at end of file diff --git a/public/local-data/currencies.json b/public/local-data/currencies.json index 933de04..ac505e8 100644 --- a/public/local-data/currencies.json +++ b/public/local-data/currencies.json @@ -1,100 +1 @@ -{ - "currencies": { - "data": [ - { - "id": "1", - "attributes": { - "code": "EUR", - "symbol": "€", - "rate_to_usd": 1.036166, - "display_decimals": true - } - }, - { - "id": "2", - "attributes": { - "code": "CAD", - "symbol": "$", - "rate_to_usd": 0.79319156, - "display_decimals": true - } - }, - { - "id": "3", - "attributes": { "code": "USD", "symbol": "$", "rate_to_usd": 1, "display_decimals": true } - }, - { - "id": "4", - "attributes": { - "code": "JPY", - "symbol": "¥", - "rate_to_usd": 0.0083864261, - "display_decimals": false - } - }, - { - "id": "5", - "attributes": { - "code": "BRL", - "symbol": "R$", - "rate_to_usd": 0.19904328, - "display_decimals": true - } - }, - { - "id": "6", - "attributes": { - "code": "GBP", - "symbol": "£", - "rate_to_usd": 1.3181323, - "display_decimals": true - } - }, - { - "id": "7", - "attributes": { - "code": "AUD", - "symbol": "$", - "rate_to_usd": 0.7422, - "display_decimals": true - } - }, - { - "id": "8", - "attributes": { - "code": "INR", - "symbol": "₹", - "rate_to_usd": 0.013162881, - "display_decimals": false - } - }, - { - "id": "9", - "attributes": { - "code": "NZD", - "symbol": "$", - "rate_to_usd": 0.69089984, - "display_decimals": true - } - }, - { - "id": "10", - "attributes": { - "code": "CHF", - "symbol": "CHF", - "rate_to_usd": 1.0728706, - "display_decimals": true - } - }, - { - "id": "11", - "attributes": { - "code": "CNY", - "symbol": "¥", - "rate_to_usd": 0.141546, - "display_decimals": true - } - } - ] - } -} +{"currencies":{"data":[{"id":"1","attributes":{"code":"EUR","symbol":"€","rate_to_usd":1.036166,"display_decimals":true}},{"id":"2","attributes":{"code":"CAD","symbol":"$","rate_to_usd":0.79319156,"display_decimals":true}},{"id":"3","attributes":{"code":"USD","symbol":"$","rate_to_usd":1,"display_decimals":true}},{"id":"4","attributes":{"code":"JPY","symbol":"¥","rate_to_usd":0.0083864261,"display_decimals":false}},{"id":"5","attributes":{"code":"BRL","symbol":"R$","rate_to_usd":0.19904328,"display_decimals":true}},{"id":"6","attributes":{"code":"GBP","symbol":"£","rate_to_usd":1.3181323,"display_decimals":true}},{"id":"7","attributes":{"code":"AUD","symbol":"$","rate_to_usd":0.7422,"display_decimals":true}},{"id":"8","attributes":{"code":"INR","symbol":"₹","rate_to_usd":0.013162881,"display_decimals":false}},{"id":"9","attributes":{"code":"NZD","symbol":"$","rate_to_usd":0.69089984,"display_decimals":true}},{"id":"10","attributes":{"code":"CHF","symbol":"CHF","rate_to_usd":1.0728706,"display_decimals":true}},{"id":"11","attributes":{"code":"CNY","symbol":"¥","rate_to_usd":0.141546,"display_decimals":true}}]}} \ No newline at end of file diff --git a/public/local-data/languages.json b/public/local-data/languages.json index c13e843..f2ea4be 100644 --- a/public/local-data/languages.json +++ b/public/local-data/languages.json @@ -1,29 +1 @@ -{ - "languages": { - "data": [ - { "id": "1", "attributes": { "name": "French", "code": "fr", "localized_name": "Français" } }, - { "id": "2", "attributes": { "name": "English", "code": "en", "localized_name": "English" } }, - { "id": "3", "attributes": { "name": "Japanese", "code": "ja", "localized_name": "日本語" } }, - { "id": "4", "attributes": { "name": "Spanish", "code": "es", "localized_name": "Español" } }, - { - "id": "6", - "attributes": { - "name": "Portuguese (Brazil)", - "code": "pt-br", - "localized_name": "Português (Brasil)" - } - }, - { "id": "8", "attributes": { "name": "German", "code": "de", "localized_name": "Deutsch" } }, - { - "id": "9", - "attributes": { "name": "Italian", "code": "it", "localized_name": "Italiano" } - }, - { - "id": "10", - "attributes": { "name": "Russian", "code": "ru", "localized_name": "русский" } - }, - { "id": "11", "attributes": { "name": "Korean", "code": "ko", "localized_name": "한국어" } }, - { "id": "12", "attributes": { "name": "Chinese", "code": "zh", "localized_name": "中文" } } - ] - } -} +{"languages":{"data":[{"id":"1","attributes":{"name":"French","code":"fr","localized_name":"Français"}},{"id":"2","attributes":{"name":"English","code":"en","localized_name":"English"}},{"id":"3","attributes":{"name":"Japanese","code":"ja","localized_name":"日本語"}},{"id":"4","attributes":{"name":"Spanish","code":"es","localized_name":"Español"}},{"id":"6","attributes":{"name":"Portuguese (Brazil)","code":"pt-br","localized_name":"Português (Brasil)"}},{"id":"8","attributes":{"name":"German","code":"de","localized_name":"Deutsch"}},{"id":"9","attributes":{"name":"Italian","code":"it","localized_name":"Italiano"}},{"id":"10","attributes":{"name":"Russian","code":"ru","localized_name":"русский"}},{"id":"11","attributes":{"name":"Korean","code":"ko","localized_name":"한국어"}},{"id":"12","attributes":{"name":"Chinese","code":"zh","localized_name":"中文"}}]}} \ No newline at end of file diff --git a/public/local-data/recorders.json b/public/local-data/recorders.json new file mode 100644 index 0000000..6bbd997 --- /dev/null +++ b/public/local-data/recorders.json @@ -0,0 +1 @@ +{"recorders":{"data":[{"attributes":{"username":"Dr_Mint","anonymize":false,"anonymous_code":"3360","pronouns":"he/him","bio":[{"bio":"Hi! I felt in love with Yoko Taro work a couple years ago. Since then, I’ve compiled a book titled YOKOVERSE – A Comprehensive Codex, and I’m now working on this website where I’ll be able to publish my scans and translations.","language":{"data":{"attributes":{"code":"en"}}}},{"bio":"Bonjour ! Il y a quelques années, je suis tombé amoureux du travail de Yoko Taro. Depuis, j'ai compilé un ouvrage intitulé YOKOVERSE - A Comprehensive Codex. Je travaille maintenant sur ce site où je publie mes scans et traductions.","language":{"data":{"attributes":{"code":"fr"}}}}],"languages":{"data":[{"attributes":{"code":"fr"}},{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":{"attributes":{"name":"Dr_Mint_profile_picture.png","alternativeText":"Dr_Mint's profile picture","caption":"Dr_Mint's profile picture","width":804,"height":804,"url":"/uploads/icon_153a18f47a.png"}}}}},{"attributes":{"username":"404errorcode","anonymize":false,"anonymous_code":"0932","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Valthier","anonymize":false,"anonymous_code":"6134","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Seviryn","anonymize":false,"anonymous_code":"7269","pronouns":"they/them","bio":[{"bio":"Hey! Welcome! I became a fan of the Yokoverse beginning with NieR:Automata in 2017. Since then I’ve done a deep dive into the NieR Lore and do my best to stay up to date on everything with this series. You may have encountered my posts on r/NieR in the past, posting news and short articles. You can find me on virtually any website under the screen name Inmate7269. 人類に栄光あれ","language":{"data":{"attributes":{"code":"en"}}}}],"languages":{"data":[{"attributes":{"code":"en"}}]},"avatar":{"data":{"attributes":{"name":"sev.jpg","alternativeText":"sev.jpg","caption":"sev.jpg","width":300,"height":300,"url":"/uploads/sev_edfc50a9e1.jpg"}}}}},{"attributes":{"username":"darius","anonymize":false,"anonymous_code":"7330","pronouns":"he/him","bio":[{"bio":"My name is Darius, I am a 20 y/o who loves DrakeNier, Star Wars and Mario. When I’m not working, I spend my time playing dodnier games, drawing, or reading. My biggest project is scanning DOD World Inside. You can contact me on my Twitter for any inquires.","language":{"data":{"attributes":{"code":"en"}}}}],"languages":{"data":[{"attributes":{"code":"en"}}]},"avatar":{"data":{"attributes":{"name":"darius.PNG","alternativeText":"darius","caption":"darius.PNG","width":280,"height":280,"url":"/uploads/darius_9bfb1e9813.PNG"}}}}},{"attributes":{"username":"Roy","anonymize":false,"anonymous_code":"8048","pronouns":"he/him","bio":[{"bio":"Hi. I’m Roy, a collector, a SciADV fan and a so called digital archaeologist. My role here is to provide visual documentation of the games pertaining to the Yoko Taro universe and share information on Japanese merchandise to western and spanish-speaking audiences. You can see more of my documentation work in the ArchaeoVG networks.","language":{"data":{"attributes":{"code":"en"}}}}],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"es"}}]},"avatar":{"data":{"attributes":{"name":"roy.jpg","alternativeText":"roy.jpg","caption":"roy.jpg","width":300,"height":300,"url":"/uploads/roy_db77078fb2.jpg"}}}}},{"attributes":{"username":"RandomFanMan1","anonymize":true,"anonymous_code":"5212","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Barnabism","anonymize":false,"anonymous_code":"5350","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"eekiehd","anonymize":false,"anonymous_code":"0999","pronouns":"he/him","bio":[],"languages":{"data":[{"attributes":{"code":"en"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Qara","anonymize":false,"anonymous_code":"0002","pronouns":null,"bio":[],"languages":{"data":[]},"avatar":{"data":null}}},{"attributes":{"username":"Jam","anonymize":false,"anonymous_code":"2835","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"maru","anonymize":false,"anonymous_code":"1292","pronouns":null,"bio":[{"bio":"Heyall! I'm Maru, Brazilian, no preference in pronouns, and even though I discovered DrakeNier last year, my first contact with Yoko Taro was when SINo was first released to Pre-register (I waited so long to play, 2 years I think?). Last year I finally got a PC that could handle Automata, so I bought the game and 100% it, after that, before Replicant 1.22 released, I made my best to play and 100% DOD1 and 3 (and 2, though that came a bit later), than, Rein launched and I got to know more people that also liked the franchise!","language":{"data":{"attributes":{"code":"en"}}}}],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"pt-br"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Kestrel","anonymize":false,"anonymous_code":"9235","pronouns":null,"bio":[],"languages":{"data":[]},"avatar":{"data":null}}},{"attributes":{"username":"kho-dazat","anonymize":false,"anonymous_code":"7383","pronouns":null,"bio":[{"bio":"[Tumblr](https://kho-dazat.tumblr.com)","language":{"data":{"attributes":{"code":"en"}}}}],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"spffn","anonymize":false,"anonymous_code":"1822","pronouns":null,"bio":[{"bio":"[Twitter](https://twitter.com/shirobooty)\n[Reddit](https://www.reddit.com/user/spffn)","language":{"data":{"attributes":{"code":"en"}}}}],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Defade","anonymize":false,"anonymous_code":"6599","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"RaizinMonk","anonymize":false,"anonymous_code":"1660","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"FFTranslations","anonymize":false,"anonymous_code":"2014","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"nier.fandom.com","anonymize":false,"anonymous_code":"1376","pronouns":null,"bio":[{"bio":"https://nier.fandom.com/wiki/","language":{"data":{"attributes":{"code":"en"}}}}],"languages":{"data":[{"attributes":{"code":"en"}}]},"avatar":{"data":null}}},{"attributes":{"username":"beefbulgogi","anonymize":false,"anonymous_code":"3303","pronouns":null,"bio":[{"bio":"Also known as dofucakes\nhttps://twitter.com/beefbulgogi","language":{"data":{"attributes":{"code":"en"}}}}],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"mint","anonymize":false,"anonymous_code":"0798","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Charming Potatoe","anonymize":false,"anonymous_code":"4949","pronouns":null,"bio":[{"bio":"Hi there! As my name suggests, I’m a potatoe. 19 years old, currently in college studying design & engineering. Fell in love with N:A throughout the pandemic and the Yokoverse as a whole sequentially (dragged by my poor feelings). The NieR & DOD3 OST bring me as much joy as depression they can give, so you could say I’m a masochist of food for thought.\n\nCurrently working with this amazing project to give a bit of our share to the DrakeNieR community. As for the work related to everything you’re seeing on this website, I’m responsible for translating (specified languages [and mainly other Romance languages]), proofreading, lore digging / analysis & website stuff.\n\nIn case anyone’s curious, favorite characters: YoRHa Unit No.2 Type ? & 0x30.\n\nPD: Accord is a beautiful mystery that needs more recognition, but all in due time.","language":{"data":{"attributes":{"code":"en"}}}},{"bio":"¡Hola! Como mi nombre indica, soy una patata. 19 años, actualmente en la universidad estudiando diseño e ingeniería. Me enamoré de N:A a lo largo de la pandemia y del Yokoverse en su conjunto secuencialmente (arrastrado por mis pobres sentimientos). La música de NieR & DOD3 me dan tanta alegría como depresión a partes iguales, por lo que se podría decir que soy un masoquista de la reflexión.\n\nActualmente trabajando con este increíble proyecto para dar un poco de nuestra parte a la comunidad de DrakeNieR. En cuanto al trabajo relacionado con todo lo que estáis viendo en este sitio web, soy responsable de las traducciones (idiomas especificados [y principalmente otros idiomas Romances]), corrección literaria, investigación / análisis del universo y material del sitio web.\n\nEn el caso que a alguien le interese, personajes favoritos: YoRHa Unit No.2 Type ? & 0x30.\n\nPD: Accord es un magnifico misterio que necesita más reconocimiento, pero todo a su debido tiempo.","language":{"data":{"attributes":{"code":"es"}}}}],"languages":{"data":[{"attributes":{"code":"fr"}},{"attributes":{"code":"en"}},{"attributes":{"code":"es"}}]},"avatar":{"data":{"attributes":{"name":"Charming Potatoe.jpg","alternativeText":"Charming Potatoe.jpg","caption":"Charming Potatoe.jpg","width":600,"height":600,"url":"/uploads/Charming_Potatoe_156323d931.jpg"}}}}},{"attributes":{"username":"Emily","anonymize":false,"anonymous_code":"0153","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Unknown","anonymize":false,"anonymous_code":"0000","pronouns":null,"bio":[],"languages":{"data":[]},"avatar":{"data":null}}},{"attributes":{"username":"Sir Thiccsalot","anonymize":false,"anonymous_code":"3936","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}}]},"avatar":{"data":null}}},{"attributes":{"username":"groof","anonymize":false,"anonymous_code":"5498","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Nyupun","anonymize":false,"anonymous_code":"2013","pronouns":"she/her","bio":[],"languages":{"data":[{"attributes":{"code":"fr"}},{"attributes":{"code":"en"}}]},"avatar":{"data":{"attributes":{"name":"dod1.3-6.webp","alternativeText":"dod1.3-6.webp","caption":"dod1.3-6.webp","width":1500,"height":1000,"url":"/uploads/dod1_3_6_79d83f888e.webp"}}}}},{"attributes":{"username":"Baddaku","anonymize":false,"anonymous_code":"1111","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"fr"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Miseii","anonymize":false,"anonymous_code":"1000","pronouns":null,"bio":[],"languages":{"data":[]},"avatar":{"data":null}}},{"attributes":{"username":"Nyhxi","anonymize":false,"anonymous_code":"9999","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"fr"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Blood Animal","anonymize":false,"anonymous_code":"2222","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}}]},"avatar":{"data":null}}},{"attributes":{"username":"elsa","anonymize":false,"anonymous_code":"9716","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"AtlasOFG","anonymize":false,"anonymous_code":"5543","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"fr"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Darky","anonymize":false,"anonymous_code":"7646","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"fr"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Bri","anonymize":false,"anonymous_code":"6172","pronouns":"she/her","bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Frichstor","anonymize":false,"anonymous_code":"2490","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"fr"}}]},"avatar":{"data":null}}},{"attributes":{"username":"jinxyface","anonymize":false,"anonymous_code":"6969","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Jonathan","anonymize":false,"anonymous_code":"9902","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Noah","anonymize":false,"anonymous_code":"9903","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}},{"attributes":{"username":"久久","anonymize":false,"anonymous_code":"8622","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"zh"}}]},"avatar":{"data":null}}},{"attributes":{"username":"黑鯵","anonymize":false,"anonymous_code":"6454","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"zh"}}]},"avatar":{"data":null}}},{"attributes":{"username":"MajAxe","anonymize":false,"anonymous_code":"8451","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"fr"}},{"attributes":{"code":"en"}}]},"avatar":{"data":null}}},{"attributes":{"username":"Nashoki","anonymize":false,"anonymous_code":"2432","pronouns":null,"bio":[],"languages":{"data":[{"attributes":{"code":"en"}},{"attributes":{"code":"ja"}}]},"avatar":{"data":null}}}]}} \ No newline at end of file diff --git a/public/local-data/typesTranslations.json b/public/local-data/typesTranslations.json new file mode 100644 index 0000000..24cdd14 --- /dev/null +++ b/public/local-data/typesTranslations.json @@ -0,0 +1 @@ +{"metadataTypes":{"data":[{"attributes":{"slug":"audio","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Audio"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Audio"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Audio"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Audio"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"音频"}]}},{"attributes":{"slug":"game","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Game"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Jeu"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Jogo"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Juego"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"游戏"}]}},{"attributes":{"slug":"textual","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Textual"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Textuel"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Texto"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Textual"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"原本"}]}},{"attributes":{"slug":"video","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Video"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Video"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Video"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Video"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"视频"}]}},{"attributes":{"slug":"mixed","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Mixed"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Mixte"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Misto"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Mixto"},{"language":{"data":null},"title":"多媒体"}]}}]},"audioSubtypes":{"data":[{"attributes":{"slug":"soundtrack","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Soundtrack"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Bande-son"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"サウンドトラック"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Trilha Sonora"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Banda Sonora"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"原声音轨"}]}},{"attributes":{"slug":"audiobook","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Audiobook"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"オーディオブック"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Livre audio"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Audiolivros"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Audio libro"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"有声书"}]}},{"attributes":{"slug":"other","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Other"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Autre"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Outros"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Otros"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"其他"}]}}]},"videoSubtypes":{"data":[{"attributes":{"slug":"dvd","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"DVD"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"DVD"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"DVD"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"DVD"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"DVD"}]}},{"attributes":{"slug":"blu-ray","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Blu-ray"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Blu-ray"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Blu-ray"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Blu-ray"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"蓝光碟"}]}}]},"textualSubtypes":{"data":[{"attributes":{"slug":"book","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Livre"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Book"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Livro"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Libro"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"资料集"}]}},{"attributes":{"slug":"manga","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Manga"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Manga"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Manga"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"漫画"}]}},{"attributes":{"slug":"comic","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Bande dessinée"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Comic"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Quadrinho"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Cómic"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"漫画"}]}},{"attributes":{"slug":"magazine","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Magazine"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Magazine"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Revista"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Revista"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"杂志"}]}},{"attributes":{"slug":"novel","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Roman"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Novel"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Novel"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Novela"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"小说"}]}},{"attributes":{"slug":"scriptbook","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Livre de scénarios"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Script Book"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Script"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Libro de guiones"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"台本"}]}},{"attributes":{"slug":"scorebook","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Recueil de partitions"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Score Book"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Livro de Partituras"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Libro de partituras"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"乐谱"}]}},{"attributes":{"slug":"photobook","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Livre de photo"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Photo Book"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Livro De Fotos"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Libro de fotos"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"写真集"}]}}]},"groupSubtypes":{"data":[{"attributes":{"slug":"item-set","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Ensemble d'items"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Item Set"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Item"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Ítem"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"物品组"}]}},{"attributes":{"slug":"variant-set","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Ensemble de variantes"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Variant Set"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Variante"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Conjunto de variantes"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"多版本组"}]}},{"attributes":{"slug":"relation-set","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Relation Set"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Ensemble apparenté"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Relacionado"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Conjunto de relaciones"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"关系组"}]}}]},"gamePlatforms":{"data":[{"attributes":{"slug":"pc","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"PC","short":"PC"}]}},{"attributes":{"slug":"ps2","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"PlayStation 2","short":"PS2"}]}},{"attributes":{"slug":"ps3","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"PlayStation 3","short":"PS3"}]}},{"attributes":{"slug":"ps4","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"PlayStation 4","short":"PS4"}]}},{"attributes":{"slug":"ps5","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"PlayStation 5","short":"PS5"}]}},{"attributes":{"slug":"xbox-360","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Xbox 360","short":"X360"}]}},{"attributes":{"slug":"xbox-one","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Xbox One","short":"XOne"}]}},{"attributes":{"slug":"switch","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Nintendo Switch","short":"Switch"}]}},{"attributes":{"slug":"ios","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"iOS","short":"iOS"}]}},{"attributes":{"slug":"android","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Android","short":"Android"}]}},{"attributes":{"slug":"java","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Java","short":"Java"}]}}]},"contentTypes":{"data":[{"attributes":{"slug":"chapter","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Chapter"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Chapitre"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Capítulo"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Capítulo"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"章节"}]}},{"attributes":{"slug":"weapon-stories","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Histoires d'armes"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Weapon Stories"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"História de Arma"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Historia de armas"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"武器故事"}]}},{"attributes":{"slug":"short-story","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Histoire courte"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Short Story"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"História Curta"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Historia Corta"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"短篇小说"}]}},{"attributes":{"slug":"interview","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Interview"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Interview"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Entrevista"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Entrevista"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"采访"}]}},{"attributes":{"slug":"illustrations","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Illustrations"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Illustrations"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Ilustrações"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Ilustraciones"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"图表"}]}},{"attributes":{"slug":"concept-art","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Concept Art"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Concept art"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"コンセプトアート"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Arte de Conceito"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Arte conceptual"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"概念原画"}]}},{"attributes":{"slug":"track","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Piste"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Track"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Pista"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Pista"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"专辑"}]}},{"attributes":{"slug":"promotional-material","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Contenu promotionel"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Promotional Material"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Material Promocional"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"宣发物料"}]}},{"attributes":{"slug":"character-guide","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Character Guide"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Guide de personnages"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Guia de Personagens"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Guía de personajes"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"角色指引"}]}},{"attributes":{"slug":"story-guide","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Guide d'histoire"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Story Guide"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Guia de História"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Guía de historia"},{"language":{"data":null},"title":"故事指引"}]}},{"attributes":{"slug":"strategy-guide","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Guide de stratégie"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Strategy Guide"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Guia de Estratégia"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"攻略指引"}]}},{"attributes":{"slug":"world-guide","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Guide du monde"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"World Guide"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Guia de Mundo"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Guía del mundo"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"世界观指引"}]}},{"attributes":{"slug":"lore-guide","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Lore Guide"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Guide de lore"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Guia de Lore"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Guía de Lore"}]}},{"attributes":{"slug":"document","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Document"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Document"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Documento"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Documento"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"文档"}]}},{"attributes":{"slug":"glossary","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Glossary"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Glossaire"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Glossário"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Glossary"},{"language":{"data":null},"title":"专有名词"}]}},{"attributes":{"slug":"chronology","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Chronology"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Chronologie"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Cronologia"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Cronología"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"年表"}]}},{"attributes":{"slug":"music-sheet","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Music Sheet"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Partition de musique"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Partitura musical"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Partitura musical"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"乐谱"}]}},{"attributes":{"slug":"lyrics","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Lyrics"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Paroles"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Letra"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Letra"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"歌词"}]}},{"attributes":{"slug":"other","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Other"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Autre"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Outros"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"其他"}]}},{"attributes":{"slug":"q-and-a","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Q&A"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Q&A"},{"language":{"data":{"attributes":{"code":"pt-br"}}},"title":"Perguntas e Respostas"},{"language":{"data":{"attributes":{"code":"es"}}},"title":"Preguntas y Respuestas (Q&A)"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"问答"}]}},{"attributes":{"slug":"job-story","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Job Story"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Histoire de classe"}]}},{"attributes":{"slug":"event","titles":[{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Événement"},{"language":{"data":{"attributes":{"code":"en"}}},"title":"Event"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"事件"}]}}]},"wikiPagesTags":{"data":[{"attributes":{"slug":"characters","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Characters"},{"language":{"data":{"attributes":{"code":"fr"}}},"title":"Personnages"}]}},{"attributes":{"slug":"places","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Places"}]}},{"attributes":{"slug":"events","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Events"}]}},{"attributes":{"slug":"terms","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Terms"}]}},{"attributes":{"slug":"enemies","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Enemies"}]}}]},"weaponStoryTypes":{"data":[{"attributes":{"slug":"axe","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Axe"},{"language":{"data":{"attributes":{"code":"es"}}},"name":"Hacha"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"斧"}]}},{"attributes":{"slug":"chakram","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Chakram"},{"language":{"data":{"attributes":{"code":"es"}}},"name":"Chacram"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"战轮"}]}},{"attributes":{"slug":"combat-bracers","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Combat Bracers"},{"language":{"data":{"attributes":{"code":"es"}}},"name":"Brazales de combate"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"拳套"}]}},{"attributes":{"slug":"hammer","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Hammer"},{"language":{"data":{"attributes":{"code":"es"}}},"name":"Martillo"},{"language":{"data":{"attributes":{"code":"fr"}}},"name":"Marteau"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"锤"}]}},{"attributes":{"slug":"longsword","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Longsword"},{"language":{"data":{"attributes":{"code":"es"}}},"name":"Espadones"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"重剑"}]}},{"attributes":{"slug":"mace","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Mace"},{"language":{"data":{"attributes":{"code":"es"}}},"name":"Mazo"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"锤矛"}]}},{"attributes":{"slug":"one-handed-sword","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"One-handed Sword"},{"language":{"data":{"attributes":{"code":"es"}}},"name":"Espadas pequeñas"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"单手剑"}]}},{"attributes":{"slug":"pole-axe","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Pole Axe"},{"language":{"data":{"attributes":{"code":"es"}}},"name":"Lanzas"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"长柄斧"}]}},{"attributes":{"slug":"rod","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Rod"},{"language":{"data":{"attributes":{"code":"es"}}},"name":"Varilla"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"棍杖"}]}},{"attributes":{"slug":"spear","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Spear"},{"language":{"data":{"attributes":{"code":"fr"}}},"name":"Lance"},{"language":{"data":null},"name":"长枪"}]}},{"attributes":{"slug":"staff","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Staff"},{"language":{"data":{"attributes":{"code":"fr"}}},"name":"Bâton"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"法杖"}]}},{"attributes":{"slug":"sword","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Sword"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"长剑"}]}},{"attributes":{"slug":"two-handed-sword","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Two-handed Sword"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"双手剑"}]}},{"attributes":{"slug":"other","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Other"},{"language":{"data":{"attributes":{"code":"es"}}},"name":"Otro"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"其他"}]}},{"attributes":{"slug":"book","translations":[{"language":{"data":{"attributes":{"code":"fr"}}},"name":"Tome"},{"language":{"data":{"attributes":{"code":"en"}}},"name":"Book"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"书"}]}},{"attributes":{"slug":"gun","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Gun"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"枪械"}]}},{"attributes":{"slug":"instrument","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Instrument"},{"language":{"data":{"attributes":{"code":"fr"}}},"name":"Instrument"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"乐器"}]}},{"attributes":{"slug":"orb","translations":[{"language":{"data":{"attributes":{"code":"en"}}},"name":"Orb"},{"language":{"data":{"attributes":{"code":"fr"}}},"name":"Orbe"}]}},{"attributes":{"slug":"bow","translations":[{"language":{"data":{"attributes":{"code":"fr"}}},"name":"Arc"},{"language":{"data":{"attributes":{"code":"en"}}},"name":"Bow"},{"language":{"data":{"attributes":{"code":"zh"}}},"name":"弓"}]}}]},"categories":{"data":[{"attributes":{"slug":"drakengard-1","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Drakengard 1","short":"DOD1"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"ドラッグ オン ドラグーン シリーズ","short":"DOD"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"龙背上的骑兵","short":"龙背"}]}},{"attributes":{"slug":"drakengard-2","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Drakengard 2","short":"DOD2"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"ドラッグオンドラグーン2","short":"DOD2"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"龙背上的骑兵2","short":"龙背2"}]}},{"attributes":{"slug":"drakengard-3","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Drakengard 3","short":"DOD3"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"ドラッグオンドラグーン3","short":"DOD3"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"龙背上的骑兵3","short":"龙背3"}]}},{"attributes":{"slug":"nier-gestalt","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"NieR Gestalt","short":"Gestalt"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"ニーア ゲシュタルト","short":"ゲシュタルト"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"尼尔 型态","short":"型态"}]}},{"attributes":{"slug":"nier-replicant","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"NieR Replicant","short":"Replicant"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"ニーア レプリカント","short":"レプリカント"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"尼尔 人工生命","short":"人工生命"}]}},{"attributes":{"slug":"nier-replicant-1-22","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"NieR Replicant ver.1.22...","short":"N1.22..."},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"尼尔 人工生命 ver.1.22474487139...","short":"人工生命 ver.1.22..."}]}},{"attributes":{"slug":"nier-automata","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"NieR:Automata","short":"N:A"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"ニーア オートマタ","short":"ニーア オートマタ"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"尼尔 自动人形","short":"自动人形"}]}},{"attributes":{"slug":"nier-reincarnation","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"NieR Re[in]carnation","short":"Rein"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"ニーア リィンカーネーション","short":"リィンカーネーション"}]}},{"attributes":{"slug":"yorha","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"YoRHa","short":"YoRHa"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"ヨルハ","short":"ヨルハ"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"寄葉","short":"寄葉"}]}},{"attributes":{"slug":"yorha-boys","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"YoRHa Boys","short":"YoRHa Boys"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"少年ヨルハ","short":"少年ヨルハ"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"少年寄葉","short":"少年寄葉"}]}},{"attributes":{"slug":"sinoalice","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"SINoALICE","short":"SINo"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"心罪爱丽丝","short":"死爱"}]}},{"attributes":{"slug":"voice-of-card","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Voice of Cards","short":"VoC"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"卡牌之声","short":null}]}},{"attributes":{"slug":"bakuken","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Bakuken","short":"Bakuken"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"爆剣","short":"爆剣"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"舞台剧《爆剑》","short":"爆剑"}]}},{"attributes":{"slug":"thou-shalt-not-die","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Thou Shalt Not Die","short":"TSND"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"君死ニタマフ事ナカレ","short":"君死ニタマフ事ナカレ"},{"language":{"data":null},"title":"愿君勿死","short":"君死"}]}},{"attributes":{"slug":"drakengard-1-3","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Drakengard 1.3","short":"DOD1.3"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"ドラッグオンドラグーン1.3","short":"DOD1.3"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"龙背上的骑兵1.3","short":"龙背1.3"}]}},{"attributes":{"slug":"drakengard-4","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Drakengard 4","short":"DOD4"},{"language":{"data":{"attributes":{"code":"ja"}}},"title":"ドラッグオンドラグーン4","short":"DOD4"},{"language":{"data":null},"title":"龙背上的骑兵4","short":"龙背4"}]}},{"attributes":{"slug":"final-fantasy-14","titles":[{"language":{"data":{"attributes":{"code":"en"}}},"title":"Final Fantasy XIV","short":"FF14"},{"language":{"data":{"attributes":{"code":"zh"}}},"title":"最终幻想14","short":"FF14"}]}}]}} \ No newline at end of file diff --git a/public/local-data/websiteInterfaces.json b/public/local-data/websiteInterfaces.json index 06e61ea..e7e69e1 100644 --- a/public/local-data/websiteInterfaces.json +++ b/public/local-data/websiteInterfaces.json @@ -1,1086 +1 @@ -{ - "websiteInterfaces": { - "data": [ - { - "attributes": { - "ui_language": { "data": { "attributes": { "code": "en" } } }, - "library": "Library", - "contents": "Contents", - "wiki": "Wiki", - "chronicles": "Chronicles", - "library_short_description": "Browse all physical and digital media", - "contents_short_description": "Explore all content and filter by type or category", - "wiki_short_description": "An encyclopedia for everything related to DrakeNieR", - "chronicles_short_description": "Experience all events and content in chronological order", - "news": "News", - "gallery": "Gallery", - "archives": "Archives", - "about_us": "About us", - "licensing_notice": "This website’s content is made available under [CC-BY-SA](https://creativecommons.org/licenses/by-sa/4.0/) unless otherwise noted.", - "copyright_notice": "Accord’s Library is not affiliated with or endorsed by SQUARE ENIX CO. LTD. All game assets and promotional materials belongs to © SQUARE ENIX CO. LTD.", - "contents_description": "All the contents (textual, audio, and video) from the Library or other online sources.", - "type": "{ count, plural, =0 {No types} one {Type} other {Types} }", - "category": "{ count, plural, =0 {No categories} one {Category} other {Categories} }", - "size": "Size", - "release_date": "Release date", - "details": "Details", - "price": "Price", - "width": "Width", - "height": "Height", - "thickness": "Thickness", - "subitem": "{ count, plural, =0 {No subitems} one {Subitem} other {Subitems} }", - "variant": "{ count, plural, =0 {No variants} one {Variant} other {Variants} }", - "summary": "Summary", - "audio": "Audio", - "video": "Video", - "textual": "Textual", - "game": "Game", - "other": "Other", - "left_to_right": "Left to right", - "right_to_left": "Right to left", - "page": "{ count, plural, =0 {No pages} one {Page} other {Pages} }", - "page_order": "Page order", - "binding": "Binding", - "type_information": "Type information", - "front_matter": "Front matter", - "back_matter": "Back matter", - "open_content": "Open content", - "view_scans": "View scans", - "paperback": "Paperback", - "hardcover": "Hardcover", - "language": "{ count, plural, =0 {No languages} one {Language} other {Languages} }", - "library_description": "A comprehensive list of all Yokoverse’s side materials (books, novellas, artbooks, stage plays, manga, drama CDs, and comics). For each, we provide photos, scans, and transcript of the content, information about what it is, when and how it was released, size, initial price…", - "wiki_description": "An encyclopedia for everything related to DrakeNieR. Right now, we only have the Chronology but a lot more pages are planned to be released!", - "chronicles_description": "Experience all events and content in chronological order.", - "news_description": "News articles written by our Recorders! Here you will find announcements about new merch/items releases, guides, theories, unboxings, showcases...", - "archives_description": "Besides physical medias, we also archive digital contents such as websites, webpages, videos, and documents.", - "about_us_description": "Find more information about the Accord's Library project in the following pages.", - "page_not_found": "Oops! We’re having trouble finding this page", - "default_description": "Accord's Library aims at gathering and archiving all of Yoko Taro’s work. Yoko Taro is a Japanese video game director and scenario writer.", - "name": "Name", - "show_subitems": "Show subitems", - "show_primary_items": "Show primary items", - "show_secondary_items": "Show secondary items", - "order_by": "Order by", - "select_option_sidebar": "Select one of the options in the sidebar", - "group": "Group", - "settings": "Settings", - "theme": "Theme", - "light": "Light", - "auto": "Auto", - "dark": "Dark", - "font_size": "Font size", - "player_name": "Player name", - "currency": "Currency", - "font": "Font", - "calculated": "Calculated", - "status_incomplete": "This entry is only partially translated/transcribed.", - "status_draft": "This entry is just a draft. It usually means that this is a work-in-progress. Translation/transcription might be poor and/or computer-generated.", - "status_review": "This entry has not yet being proofread. The content should still be accurate.", - "status_done": "This entry has been checked and proofread. If you notice any translation errors or typos, please contact us so we can fix it!", - "incomplete": "Incomplete", - "draft": "Draft", - "review": "Review", - "done": "Done", - "status": "Status", - "transcript_notice": "This content is a transcript", - "translation_notice": "This content is a fan-translation", - "source_language": "Source language", - "pronouns": "Pronouns", - "item": "{ count, plural, =0 {No items} one {Item} other {Items} }", - "open_settings": "Open settings", - "open_search": "Open search", - "chronology": "Chronology", - "accords_handbook": "Accord's Handbook", - "legality": "Legality", - "sharing_policy": "Sharing Policy", - "contact_us": "Contact us", - "email": "Email", - "email_gdpr_notice": "We only use your email in order to contact you in regard to your request. We do not share this email with anyone nor use it for any other purpose.", - "message": "Message", - "send": "Send", - "response_invalid_code": "Verification code is incorrect.", - "response_invalid_email": "Please enter a valid email address!", - "response_email_success": "Thank you for contacting us! We will be in touch with you shortly.", - "always_show_info": "Always show info", - "item_not_available": "This item is not for sale or is no longer available", - "primary_language": "Primary language", - "secondary_language": "Secondary languages", - "previous_content": "{ count, plural, =0 {No previous content} one {Previous content} other {Previous contents} }", - "followup_content": "{ count, plural, =0 {No follow-up content} one {Follow-up content} other {Follow-up contents} }", - "videos": "Videos", - "view_on_x": "View on {x}", - "channel": "Channel", - "subscribers": "Subscribers", - "description": "Description", - "available_at_x": "Available at {x}", - "want_it": "I want it!", - "have_it": "I have it!", - "source": "Source", - "reset_all_filters": "Reset all filters", - "only_display_items_i_have": "Only display items marked as “I have”", - "only_display_items_i_want": "Only display items marked as “I want”", - "only_display_unmarked_items": "Only display unmarked items", - "table_of_contents": "Table of Contents", - "no_results_message": "No results. You can try changing or resetting the search parameters.", - "all": "All", - "special_pages": "Special Pages", - "scan": "Scan", - "scanlation": "Scanlation", - "scanners": "Scanners", - "cleaners": "Cleaners", - "typesetters": "Typesetters", - "notes": "Notes", - "tags": "Tags", - "no_source_warning": "No source!", - "copy_anchor_link": "Click to copy the archor link", - "anchor_link_copied": "Copied! 👍", - "folders": "Folders", - "empty_folder_message": "This folder is empty", - "switch_to_grid_view": "Switch to grid view", - "switch_to_folder_view": "Switch to folder view", - "paper_texture": "Paper texture", - "book_fold": "Book fold", - "lighting": "Lighting", - "side_pages": "Side pages", - "shadow": "Shadow", - "night_reader": "Night reader", - "single_page_view": "Single page view", - "double_page_view": "Double page view", - "reset_all_options": "Reset all options", - "reading_layout": "Reading layout", - "quality": "Quality", - "only_unavailable_videos": "Only unavailable videos", - "oldest": "Oldest", - "newest": "Newest", - "least_popular": "Least popular", - "most_popular": "Most popular", - "shortest": "Shortest", - "longest": "Longest", - "search": "Search", - "showing_x_out_of_y_results": "Showing {x} out of {y} results", - "return_to_x": "Return { x, select, undefined {} other {to {x}} }", - "x_results": "{ x, plural, =0 {No results} one {# result} other {# results} }", - "definition_x": "Definition {x}", - "subitem_of_x": "Subitem of {x}", - "dark_mode_extension_warning": "This website offers a light and dark theme. If you are using a \"dark mode\" browser extension, make sure to disable it for an optimal experience.", - "weapon": "{ count, plural, =0 {No weapons} one {Weapon} other {Weapons} }", - "weapons_description": "A list of all the weapons across all of the games. All distinguished weapons come with an “account.” It’s a document with various details like how the weapon was forged and how it’s been used in the past.", - "level_x": "Level {x}", - "story_x": "Story {x}", - "player_name_tooltip": "Certain in-game texts use the player's name as part of the dialogue/narration. If you want to see your name in the transcript found on this website, feel free to enter your player's name here. If left empty, '(player)' will be used instead.", - "download_archive": "Download archive", - "search_placeholder": "Search...", - "performance_mode": "Performance mode", - "performance_mode_tooltip": "This option improves performances by reducing certain visual effects (blurry backgrounds, shadows...). This mode is enabled by default on Linux, iOS, and Safari. This mode cannot be disabled on iOS or Safari as the experience would be too poor.", - "transcriber": "{ count, plural, =0 {No transcriber} one {Transcriber} other {Transcribers} }", - "translator": "{ count, plural, =0 {No translator} one {Translator} other {Translators} }", - "proofreader": "{ count, plural, =0 {No proofreader} one {Proofreader} other {Proofreaders} }", - "dubber": "{ count, plural, =0 {No dubber} one {Dubber} other {Dubbers} }", - "subber": "{ count, plural, =0 {No subber} one {Subber} other {Subbers} }", - "author": "{ count, plural, =0 {No author} one {Author} other {Authors} }" - } - }, - { - "attributes": { - "ui_language": { "data": { "attributes": { "code": "fr" } } }, - "library": "Bibliothèque", - "contents": "Contenus", - "wiki": "Wiki", - "chronicles": "Chroniques", - "library_short_description": "Explorer l'ensemble des médias physique ou numérique", - "contents_short_description": "Explorer tout les contenus et filtrer par type ou par catégorie", - "wiki_short_description": "Une encyclopédie pour tout l'univers DrakeNieR", - "chronicles_short_description": "Parcourir tous les événements et les contenu dans l'ordre chronologique", - "news": "News", - "gallery": "Galerie", - "archives": "Archives", - "about_us": "À propos", - "licensing_notice": "Le contenu de ce site web est mis à disposition sous licence [CC-BY-SA](https://creativecommons.org/licenses/by-sa/4.0/), sauf indication contraire.", - "copyright_notice": "Accord's Library n'est pas affiliée ni approuvée par SQUARE ENIX CO. LTD. Tous les contenus du jeu et les contenus promotionnel appartiennent à © SQUARE ENIX CO. LTD.", - "contents_description": "Tous les contenus (textuels, audio et vidéo) de la Bibliothèque ou d'autres sources en ligne.", - "type": "{ count, plural, =0 {Pas de type} one {Type} other {Types} }", - "category": "{ count, plural, =0 {Pas de catégorie} one {Catégorie} other {Catégories} }", - "size": "Dimension", - "release_date": "Date de sortie", - "details": "Détails", - "price": "Prix", - "width": "Largeur", - "height": "Hauteur", - "thickness": "Épaisseur", - "subitem": "{ count, plural, =0 {Pas de sous-item} one {Sous-item} other {Sous-items} }", - "variant": "{ count, plural, =0 {Pas de variante} one {Variante} other {Variantes} }", - "summary": "Résumé", - "audio": "Audio", - "video": "Vidéo", - "textual": "Textuel", - "game": "Jeux", - "other": "Autre", - "left_to_right": "Gauche à droite", - "right_to_left": "Droite à gauche", - "page": "{ count, plural, =0 {Aucune page} one {Page} other {Pages} }", - "page_order": "Order des pages", - "binding": "Brochure", - "type_information": "Information de type", - "front_matter": "Avant propos", - "back_matter": "Après propos", - "open_content": "Parcourir le contenu", - "view_scans": "Voir les scans", - "paperback": "Broché", - "hardcover": "Relié", - "language": "{ count, plural, =0 {Aucune langue} one {Langue} other {Langues} }", - "library_description": "Une liste complète de tous les médias annexes du Yokoverse (livres, romans, artbooks, pièces de théâtre, mangas, CD de théâtre et bandes dessinées). Pour chacun, nous fournissons des photos, des scans et une transcription du contenu, des informations sur sa nature, quand il est sorti, sa taille, son prix initial...", - "wiki_description": "Une encyclopédie pour tout ce qui concerne DrakeNieR. Pour l'instant, nous n'avons que la Chronologie mais beaucoup plus de pages sont prévues !", - "chronicles_description": "Découvrez tous les événements et contenus de manière chronologique.", - "news_description": "Articles d'actualité écrits par nos Recorders ! Vous trouverez ici des annonces sur les nouvelles sorties de merch/items, des guides, des théories, des unboxings, des showcases...", - "archives_description": "Outre les supports physiques, nous archivons également les contenus numériques tels que les sites web, les pages web, les vidéos et les documents.", - "about_us_description": "Vous trouverez plus d'informations sur le projet Accord's Library dans les pages suivantes.", - "page_not_found": "Page introuvable", - "default_description": "Accord's Library a pour but de rassembler et d'archiver l'ensemble des travaux de Yoko Taro. Yoko Taro est un réalisateur et scénariste de jeux vidéo japonais.", - "name": "Nom", - "show_subitems": "Afficher les sous-items", - "show_primary_items": "Afficher les items primaires", - "show_secondary_items": "Afficher les items secondaires", - "order_by": "Ordonné par", - "select_option_sidebar": "Sélectionner l'une des options de la barre latérale", - "group": "Groupe", - "settings": "Paramètres", - "theme": "Thème", - "light": "Clair", - "auto": "Auto", - "dark": "Sombre", - "font_size": "Taille de la police", - "player_name": "Nom du joueur", - "currency": "Devise", - "font": "Police d'écriture", - "calculated": "Calculé", - "status_incomplete": "Cette entrée n'est que partiellement traduite/transcrite.", - "status_draft": "Cette entrée n'est qu'un brouillon. Cela signifie généralement qu'il s'agit d'un travail en cours. La traduction/transcription peut être médiocre et/ou auto-générée par ordinateur.", - "status_review": "Cet entrée n'a pas encore été relue. Le contenu devrait néanmoins être correct.", - "status_done": "Cet entrée a été vérifiée et corrigée. Si vous remarquez des erreurs de traduction ou des fautes de frappe, veuillez nous contacter afin que nous puissions les corriger !", - "incomplete": "Incomplet", - "draft": "Ébauche", - "review": "Pour vérification", - "done": "Terminé", - "status": "Statut", - "transcript_notice": "Ceci est une transcription", - "translation_notice": "Ceci est une traduction", - "source_language": "Langue source", - "pronouns": "Pronoms", - "item": "{ count, plural, =0 {Aucun item} one {Item} other {Items} }", - "open_settings": "Ouvrir les paramètres", - "open_search": "Ouvrir le menu de recherche", - "chronology": "Chronologie", - "accords_handbook": "Le manuel de Accord", - "legality": "Légalité", - "sharing_policy": "Politique de partage", - "contact_us": "Nous contacter", - "email": "Email", - "email_gdpr_notice": "Nous utilisons votre adresse électronique uniquement pour vous contacter au sujet de votre demande. Nous ne partageons cette adresse avec personne et ne l'utilisons pas à d'autres fins.", - "message": "Message", - "send": "Envoyer", - "response_invalid_code": "Le code de vérification est incorrect.", - "response_invalid_email": "Veuillez saisir une adresse électronique valide !", - "response_email_success": "Merci de nous avoir contactés ! Nous prendrons contact avec vous sous peu.", - "always_show_info": "Toujours montrer les informations", - "item_not_available": "Cet article n'est pas à vendre ou n'est plus disponible.", - "primary_language": "Langue principale", - "secondary_language": "Langues secondaires", - "previous_content": "Contenu précédent", - "followup_content": "Contenu suivant", - "videos": "Videos", - "view_on_x": "Voir sur {x}", - "channel": "Chaîne", - "subscribers": "Abonnés", - "description": "Description", - "available_at_x": "Disponible sur {x}", - "want_it": "Je le veux !", - "have_it": "Je l'ai !", - "source": "Source", - "reset_all_filters": "Réinitialiser les filtres", - "only_display_items_i_have": "Seulement afficher les items marqués avec \"je le veux\"", - "only_display_items_i_want": "Seulement afficher les items marqués avec \"je l'ai\"", - "only_display_unmarked_items": "Seulement afficher les items non-marqués", - "table_of_contents": "Sommaire", - "no_results_message": "Aucun résultat. Vous pouvez essayer de modifier ou de réinitialiser les paramètres de recherche.", - "all": "Tous", - "special_pages": "Pages spéciales", - "scan": "Scan", - "scanlation": "Scantrad", - "scanners": "Scanneurs", - "cleaners": "Nettoyeurs", - "typesetters": "Lettreurs", - "notes": "Notes", - "tags": "Tags", - "no_source_warning": "Pas de source !", - "copy_anchor_link": "Cliquez pour copier le permalien", - "anchor_link_copied": "Copié ! 👍", - "folders": "Dossiers", - "empty_folder_message": "Ce dossier est vide", - "switch_to_grid_view": "Vue en grille", - "switch_to_folder_view": "Vue par dossier", - "paper_texture": "Texture de papier", - "book_fold": "Pliure du livre", - "lighting": "Effet de lumière", - "side_pages": "Tranche du livre", - "shadow": "Ombre portée", - "night_reader": "Mode nuit", - "single_page_view": "Vue 1 page", - "double_page_view": "Vue 2 pages", - "reset_all_options": "Réinitialiser les options", - "reading_layout": "Mode de lecture", - "quality": "Qualité", - "only_unavailable_videos": "Seulement les vidéos indisponibles", - "oldest": "Plus anciennes", - "newest": "Plus récentes", - "least_popular": "Plus populaires", - "most_popular": "Moins populaires", - "shortest": "Plus courtes", - "longest": "Plus longues", - "search": "Rechercher", - "showing_x_out_of_y_results": "{x} résultats sur {y} affichés", - "return_to_x": "Retour { x, select, undefined {} other {à {x}} }", - "x_results": "{ x, plural, =0 {Pas de résultat} one {# résultat} other {# résultats} }", - "definition_x": "Définition {x}", - "subitem_of_x": "Sous-item de {x}", - "dark_mode_extension_warning": "Ce site web propose un thème clair et un thème sombre. Si vous utilisez une extension de navigateur qui simule un thème sombre, veillez à la désactiver pour une expérience optimale.", - "weapon": "{ count, plural, =0 {Pas d'arme} one {Arme} other {Armes} }", - "weapons_description": "Une liste de toutes les armes présentes dans tous les jeux. Toutes les armes distinguées sont accompagnées d'un \"compte\". Il s'agit d'un document contenant divers détails tels que la façon dont l'arme a été forgée et comment elle a été utilisée dans le passé.", - "level_x": "Niveau {x}", - "story_x": "Histoire {x}", - "player_name_tooltip": "Certains textes dans les jeux utilisent le nom du joueur dans les dialogue/la narration. Si vous voulez voir votre nom dans les transcriptions se trouvant sur ce site web, n'hésitez pas à entrer votre nom de joueur ici. S'il n'est pas renseigné, '(player)' sera utilisé à la place.", - "download_archive": "Télécharger l'archive", - "search_placeholder": "Rechercher ...", - "performance_mode": "Mode performance", - "performance_mode_tooltip": "Cette option permet d'améliorer les performances en réduisant certains effets visuels (flous, ombres...). Ce mode est activé par défaut sur Linux, iOS et Safari. Ce mode ne peut pas être désactivé sur iOS ou Safari car l'expérience serait trop mauvaise.", - "transcriber": "{ count, plural, =0 {Pas de transcripteur} one {Transcripteur} other {Transcripteurs} }", - "translator": "{ count, plural, =0 {Pas de traducteur} one {Traducteur} other {Traducteurs} }", - "proofreader": "{ count, plural, =0 {Pas de correcteur} one {Correcteur} other {Correcteurs} }", - "dubber": "{ count, plural, =0 {Pas de doubleur} one {Doubleur} other {Doubleurs} }", - "subber": "{ count, plural, =0 {Pas de sous-titreur} one {Sous-titreur} other {Sous-titreurs} }", - "author": "{ count, plural, =0 {Pas d'auteur} one {Auteur} other {Auteurs} }" - } - }, - { - "attributes": { - "ui_language": { "data": { "attributes": { "code": "ja" } } }, - "library": "ライブラリー", - "contents": "コンテンツ", - "wiki": "ウィキ", - "chronicles": "クロニクル", - "library_short_description": "すべての物理メディアとデジタルメディアを見る", - "contents_short_description": "すべてのコンテンツを検索し、種類やカテゴリーで絞り込むことができます。", - "wiki_short_description": "ゲーム宇宙に関連するすべての百科事典です。", - "chronicles_short_description": "すべてのイベントとコンテンツを時系列で体験できる", - "news": "ニュース", - "gallery": "ギャラリー", - "archives": "アーカイブス", - "about_us": "会社概要", - "licensing_notice": "このウェブサイトのコンテンツは、特に断りのない限り [CC-BY-SA](https://creativecommons.org/licenses/by-sa/4.0/) で提供されています。", - "copyright_notice": "Accord's Libraryは、株式会社スクウェア・エニックスと提携、または推奨しているものではありません。株式会社スクウェア・エニックスの登録商標です。すべてのゲーム資産およびプロモーション素材は、© SQUARE ENIX CO. LTD.に帰属します。", - "contents_description": "図書館や他のオンラインソースのすべてのコンテンツ(テキスト、オーディオ、ビデオ)。", - "type": "タイプ", - "category": "カテゴリー", - "size": "サイズ", - "release_date": "発売日", - "details": "詳細", - "price": "価格", - "width": "幅", - "height": "高さ", - "thickness": "厚み", - "subitem": "サブアイテム", - "variant": "バリアント", - "summary": "概要", - "audio": "オーディオ", - "video": "ビデオ", - "textual": "テキスト", - "game": "ゲーム", - "other": "他", - "left_to_right": "左から右へ", - "right_to_left": "右から左へ", - "page": "ページ", - "page_order": "ページ順序", - "binding": "製本", - "type_information": "タイプ情報", - "front_matter": "フロントマター", - "back_matter": "バックナンバー", - "open_content": "コンテンツを開放", - "view_scans": "スキャンを開放", - "paperback": "ペーパーバック", - "hardcover": "ハードカバー", - "language": "言語", - "library_description": "ヨコベースの副教材(書籍、小説、画集、舞台劇、漫画、ドラマCD、コミック)を網羅したリストです。それぞれについて、写真、スキャン、内容の書き起こし、どんなものなのか、いつ、どのように発売されたのか、サイズ、初回価格...などの情報を掲載しています。", - "wiki_description": "DrakeNieRに関連するすべての百科事典です。現在は年表のみですが、今後多くのページを公開予定です", - "chronicles_description": "Accord's Libraryは、ヨーコ・タローの全作品を収集・保存することを目的としています。ヨーコ・タローは、日本のゲームディレクター、シナリオライターです。", - "news_description": "レコーダーが書いたニュース記事です ここでは、新しい商品/アイテムのリリースに関するお知らせ、ガイド、セオリー、アンボックス、ショーケース...をご紹介しています。", - "archives_description": "", - "about_us_description": "Accord's Libraryプロジェクトについては、以下のページで詳しくご紹介しています。", - "page_not_found": "ページが見つかりません", - "default_description": "Accord's Libraryは、ヨーコ・タローの全作品を収集・保存することを目的としています。ヨーコ・タローは、日本のゲームディレクター、シナリオライターです。", - "name": "名称", - "show_subitems": "サブアイテムをみせる", - "show_primary_items": "一次のイテムをみせる", - "show_secondary_items": "二次のイテムをみせる", - "order_by": "注文する", - "select_option_sidebar": "サイドバーのオプションを選択します", - "group": "グループ", - "settings": "設定", - "theme": "テーマ", - "light": "光", - "auto": "オート", - "dark": "暗", - "font_size": "文字サイズ", - "player_name": "プレイヤー名", - "currency": "通貨", - "font": "文字", - "calculated": "計算された", - "status_incomplete": "このエントリーは一部のみ翻訳/転記されています。", - "status_draft": "このエントリーはあくまで下書きです。通常、これは作業中であることを意味します。翻訳/転写は稚拙であったり、コンピュータで作成されたものであったりするかもしれません。", - "status_review": "このエントリーはまだ校正されていません。内容はまだ正確であるはずです。", - "status_done": "このエントリーは、チェックと校正を行いました。もし、翻訳ミスや誤字脱字にお気づきの際は、修正いたしますので、ご連絡ください", - "incomplete": "未完成", - "draft": "ドラフト", - "review": "レビュー", - "done": "完了", - "status": "状況", - "transcript_notice": "このコンテンツは転写です", - "translation_notice": "このコンテンツはファンによる翻訳です", - "source_language": "ソース言語", - "pronouns": "代名詞", - "item": "項目", - "open_settings": "オープン設定", - "open_search": "オープンサーチ", - "chronology": "年表", - "accords_handbook": "アコードの手引き", - "legality": "合法性", - "sharing_policy": "共有ポリシー", - "contact_us": "お問い合わせ", - "email": "電子メール", - "email_gdpr_notice": "お客様の電子メールは、お客様のご要望に関してご連絡するためにのみ使用します。この電子メールを誰かと共有したり、他の目的で使用することはありません。", - "message": "メッセージ", - "send": "送信", - "response_invalid_code": "検証コードが正しくありません。", - "response_invalid_email": "有効なEメールアドレスを入力してください", - "response_email_success": "お問い合わせありがとうございます。折り返しご連絡させていただきます。", - "always_show_info": "常に情報を表示する", - "item_not_available": "この商品は非売品です", - "primary_language": "主要言語", - "secondary_language": "二次言語", - "previous_content": "前のコンテンツ", - "followup_content": "フォローアップコンテンツ", - "videos": "動画", - "view_on_x": null, - "channel": "チャンネル", - "subscribers": "サブスクライバー", - "description": "説明", - "available_at_x": null, - "want_it": "欲しいです!", - "have_it": "持ってます!", - "source": "出典", - "reset_all_filters": "すべてのフィルタをリセットする", - "only_display_items_i_have": "\"持ってる \"と表示されているもののみ表示", - "only_display_items_i_want": "\"欲しい \"とマークされたものだけを表示する", - "only_display_unmarked_items": "無印のアイテムのみ表示", - "table_of_contents": "目次", - "no_results_message": "結果が出ません。検索条件を変更またはリセットしてみてください。", - "all": "すべて", - "special_pages": "特設ページ", - "scan": null, - "scanlation": null, - "scanners": null, - "cleaners": null, - "typesetters": null, - "notes": null, - "tags": null, - "no_source_warning": null, - "copy_anchor_link": null, - "anchor_link_copied": null, - "folders": null, - "empty_folder_message": null, - "switch_to_grid_view": null, - "switch_to_folder_view": null, - "paper_texture": null, - "book_fold": null, - "lighting": null, - "side_pages": null, - "shadow": null, - "night_reader": null, - "single_page_view": null, - "double_page_view": null, - "reset_all_options": null, - "reading_layout": null, - "quality": null, - "only_unavailable_videos": null, - "oldest": null, - "newest": null, - "least_popular": null, - "most_popular": null, - "shortest": null, - "longest": null, - "search": null, - "showing_x_out_of_y_results": null, - "return_to_x": null, - "x_results": null, - "definition_x": null, - "subitem_of_x": null, - "dark_mode_extension_warning": null, - "weapon": null, - "weapons_description": null, - "level_x": null, - "story_x": null, - "player_name_tooltip": null, - "download_archive": null, - "search_placeholder": null, - "performance_mode": null, - "performance_mode_tooltip": null, - "transcriber": null, - "translator": null, - "proofreader": null, - "dubber": null, - "subber": null, - "author": null - } - }, - { - "attributes": { - "ui_language": { "data": { "attributes": { "code": "es" } } }, - "library": "Librería", - "contents": "Contenidos", - "wiki": "Wiki", - "chronicles": "Crónicas", - "library_short_description": "Explora todos los medios físicos y digitales", - "contents_short_description": "Explora todo el contenido y filtra por tipo o categoría", - "wiki_short_description": "Una enciclopedia para todo lo relacionado con DrakeNieR", - "chronicles_short_description": "Experimenta todos los eventos y contenidos en orden cronológico", - "news": "Novedades", - "gallery": "Galería", - "archives": "Archivos", - "about_us": "Sobre nosotros", - "licensing_notice": "El contenido de este sitio web está disponible bajo [CC-BY-SA](https://creativecommons.org/licenses/by-sa/4.0/) a menos que se indique lo contrario.", - "copyright_notice": "Accord's Library no está afiliada ni respaldada por SQUARE ENIX CO. LTD. Todos los archivos de los juegos y material promocional pertenecen a © SQUARE ENIX CO. LTD.", - "contents_description": "Todo el contenido (textual, audio y video) de la Biblioteca u otras fuentes en línea.", - "type": "Tipo", - "category": "Categoría", - "size": "Tamaño", - "release_date": "Fecha de lanzamiento", - "details": "Detalles", - "price": "Precio", - "width": "Ancho", - "height": "Altura", - "thickness": "Grosor", - "subitem": "Sub-item", - "variant": "Variante", - "summary": "Sumario", - "audio": "Audio", - "video": "Video", - "textual": "Textual", - "game": "Juego", - "other": "Otros", - "left_to_right": "Izquierda a derecha", - "right_to_left": "Derecha a izquierda", - "page": "Página", - "page_order": "Orden de las páginas", - "binding": "Encuadernación", - "type_information": "Tipo de información", - "front_matter": "Anteportada", - "back_matter": "Portada anterior", - "open_content": "Abrir contenido", - "view_scans": "Ver escaneos", - "paperback": "Tapa blanda", - "hardcover": "Tapa dura", - "language": "Idioma", - "library_description": "Una lista completa de todos los materiales complementarios de Yokoverse (libros, novelas, libros de arte, obras de teatro, manga, CDs novelizados y cómics). Para cada uno, proporcionamos fotos, escaneos y transcripciones del contenido, información sobre qué es, cuándo y cómo se ha publicado, tamaño, precio inicial...", - "wiki_description": "Una enciclopedia para todo lo relacionado con DrakeNieR. En este momento, solo tenemos la Cronología, ¡pero muchas más páginas están planeadas para ser publicadas!", - "chronicles_description": "", - "news_description": "¡Nuevos artículos escritos por nuestros/as Archivistas! Aquí encontrarás anuncios sobre nuevos lanzamientos de merchandising/artículos, guías, teorías, unboxings, showcases...", - "archives_description": "", - "about_us_description": "Encuentra más información sobre el proyecto de Accord's Library en las siguientes páginas.", - "page_not_found": "Página no encontrada", - "default_description": "Accord's Library tiene como objetivo recopilar y archivar todo el trabajo de Yoko Taro. Yoko Taro es un director de videojuegos y escritor de escenarios japonés.", - "name": "Nombre", - "show_subitems": "Mostrar sub-items", - "show_primary_items": "Mostrar items principales", - "show_secondary_items": "Mostrar items secundarios", - "order_by": "Ordenar por", - "select_option_sidebar": "Selecciona una de las opciones en la barra lateral", - "group": "Grupo", - "settings": "Ajustes", - "theme": "Tema", - "light": "Claro", - "auto": "Automático", - "dark": "Oscuro", - "font_size": "Tamaño de la fuente", - "player_name": "Nombre del jugador/a", - "currency": "Divisa", - "font": "Fuente", - "calculated": "Calculada", - "status_incomplete": "Esta entrada está solo parcialmente traducida/transcrita.", - "status_draft": "Esta entrada es solo un borrador. Por lo general, significa que se trata de un trabajo en curso. La traducción/transcripción puede ser deficiente y/o generada por ordenador.", - "status_review": "Esta entrada aún no ha sido corregida. No obstante, el contenido debería ser preciso.", - "status_done": "Esta entrada ha sido revisada y corregida. Si notas algún error de traducción o error tipográfico, contáctanos para que podamos solucionarlo!", - "incomplete": "Incompleto", - "draft": "Borrador", - "review": "Revisado", - "done": "Completado", - "status": "Estado", - "transcript_notice": "Este contenido es una transcripción", - "translation_notice": "Este contenido es una traducción de fans", - "source_language": "Idioma original", - "pronouns": "Pronombres", - "item": "Ítem", - "open_settings": "Abrir ajustes", - "open_search": "Abrir búsqueda", - "chronology": "Cronología", - "accords_handbook": "Manual de Accord", - "legality": "Legalidad", - "sharing_policy": "Política de Uso Compartido", - "contact_us": "Contáctanos", - "email": "Email", - "email_gdpr_notice": "Solo usamos tu correo electrónico exclusivamente para contactarte en relación a tu solicitud. No compartimos este correo electrónico con nadie ni lo usamos para ningún otro propósito.", - "message": "Mensaje", - "send": "Enviar", - "response_invalid_code": "El código de verificación es incorrecto.", - "response_invalid_email": "¡Por favor, introduce una dirección de correo electrónico válida!", - "response_email_success": "¡Gracias por contactarnos! Nos pondremos en contacto contigo en breve.", - "always_show_info": "Siempre mostrar la información", - "item_not_available": "Ítem no disponible", - "primary_language": "Idioma primario", - "secondary_language": "Idioma secundario", - "previous_content": "Contenido anterior", - "followup_content": "Contenido siguiente", - "videos": "Vídeos", - "view_on_x": null, - "channel": "Canal", - "subscribers": "Suscriptores", - "description": "Descripción", - "available_at_x": "Disponible en {x}", - "want_it": "Lo quiero!", - "have_it": "Lo tengo!", - "source": "Fuente", - "reset_all_filters": "Restablecer todos los filtros", - "only_display_items_i_have": "Sólo mostrar lo que ya tengo", - "only_display_items_i_want": "Sólo mostrar lo que quiero", - "only_display_unmarked_items": "Sólo mostrar ítems sin marcación", - "table_of_contents": "Tabla de contenido", - "no_results_message": "No hay resultados", - "all": "Todos", - "special_pages": "Páginas especiales", - "scan": "Escaneos", - "scanlation": "Escaneo/Traducción", - "scanners": "Escaneadores", - "cleaners": "Limpiadores", - "typesetters": "Maquetadores", - "notes": "Notas", - "tags": "Etiquetas", - "no_source_warning": "No hay fuente", - "copy_anchor_link": "Copiar enlace de anclaje", - "anchor_link_copied": "Enlace de anclaje copiado", - "folders": "Carpetas", - "empty_folder_message": "Carpeta vacía", - "switch_to_grid_view": "Cambiar a vista de retícula", - "switch_to_folder_view": "Cambiar a vista de carpeta", - "paper_texture": "Papel texturizado", - "book_fold": "Tapa dura", - "lighting": "Iluminación", - "side_pages": "Contraportada", - "shadow": "Sombra", - "night_reader": "Lector nocturno", - "single_page_view": "Vista de página única", - "double_page_view": "Vista de página doble", - "reset_all_options": "Restablecer todas las opciones", - "reading_layout": "Disposición de lectura", - "quality": "Calidad", - "only_unavailable_videos": null, - "oldest": null, - "newest": null, - "least_popular": null, - "most_popular": null, - "shortest": null, - "longest": null, - "search": null, - "showing_x_out_of_y_results": null, - "return_to_x": null, - "x_results": null, - "definition_x": null, - "subitem_of_x": null, - "dark_mode_extension_warning": null, - "weapon": null, - "weapons_description": null, - "level_x": null, - "story_x": null, - "player_name_tooltip": null, - "download_archive": null, - "search_placeholder": null, - "performance_mode": null, - "performance_mode_tooltip": null, - "transcriber": null, - "translator": null, - "proofreader": null, - "dubber": null, - "subber": null, - "author": null - } - }, - { - "attributes": { - "ui_language": { "data": { "attributes": { "code": "pt-br" } } }, - "library": "Coleção", - "contents": "Conteúdos", - "wiki": "Wiki", - "chronicles": "Crônicas", - "library_short_description": "Procure por todas mídias digitais e físicas", - "contents_short_description": "Explore todo o conteúdo e filtre por categorias e tipos", - "wiki_short_description": "Uma enciclopédia com tudo relacionado a DrakeNieR", - "chronicles_short_description": "Explore as crônicas de DrakeNieR em ordem cronológica.", - "news": "Notícias", - "gallery": "Galeria", - "archives": "Arquivos", - "about_us": "Sobre Nós", - "licensing_notice": "O conteúdo nesse site está disponível pela CC-BY-SA, a não ser que esteja anotado.", - "copyright_notice": "Accord's Library não é afiliada ou reconhecida pela SQUARE ENIX CO. LTD. Todos assets de jogos e materiais promocionais pertencem a © SQUARE ENIX CO. LTD.\n\n", - "contents_description": "", - "type": "Tipo", - "category": "Categoria", - "size": "Tamanho", - "release_date": "Dia de lançamento", - "details": "Detalhes", - "price": "Preço", - "width": "Largura", - "height": "Altura", - "thickness": "Grossura", - "subitem": "Subitem", - "variant": "Variante", - "summary": "Sumário", - "audio": "Audio", - "video": "Video", - "textual": "Textos", - "game": "Jogos", - "other": "Outros", - "left_to_right": "Esquerda para direita", - "right_to_left": "Direita para esquerda", - "page": "Página", - "page_order": "Ordem de páginas", - "binding": "Encadernação", - "type_information": "Informação do tipo", - "front_matter": "Pré textual", - "back_matter": "Pós textual", - "open_content": "Abrir conteúdo", - "view_scans": "Ver scans", - "paperback": "Brochura", - "hardcover": "Capa dura", - "language": "Língua", - "library_description": "", - "wiki_description": null, - "chronicles_description": null, - "news_description": "", - "archives_description": "", - "about_us_description": "", - "page_not_found": "Página não encontrada", - "default_description": null, - "name": "Nome", - "show_subitems": "Mostrar subitens", - "show_primary_items": "Mostrar itens primários", - "show_secondary_items": "Mostrar itens secundários", - "order_by": "Ordenar por", - "select_option_sidebar": "Selecione uma opção na aba lateral", - "group": "Grupo", - "settings": "Configurações", - "theme": "Tema", - "light": "Claro", - "auto": "Automático", - "dark": "Escuro", - "font_size": "Tamanho da fonte", - "player_name": "Nome do jogador", - "currency": "Moeda", - "font": "Fonte", - "calculated": "Calculado", - "status_incomplete": "Este conteúdo está incompleto e não foi traduzido/transcrito completamente.", - "status_draft": "A tradução/transcrição selecionada é um Rascunho. Isso significa que a tradução pode estar fraca e/ou ter sido gerada por uma inteligência artificial.", - "status_review": "Este conteúdo ainda não foi Revisado, erros gramaticais podem ser encontrados uma vez que os revisores ainda não leram a tradução.", - "status_done": "O conteúdo foi completamente traduzido e revisado.", - "incomplete": "Incompleto", - "draft": "Rascunho", - "review": "Review", - "done": "Concluido", - "status": "Status", - "transcript_notice": "Este conteúdo foi transcrito.", - "translation_notice": "Este conteúdo é uma tradução de fã.", - "source_language": "Língua original", - "pronouns": "Pronomes", - "item": "Item", - "open_settings": "Abrir configurações", - "open_search": "Abrir pesquisa", - "chronology": "Cronologia", - "accords_handbook": "Livro de mão da Accord", - "legality": "Legalidade", - "sharing_policy": "Política de compartilhamento", - "contact_us": "Fale conosco", - "email": null, - "email_gdpr_notice": null, - "message": null, - "send": null, - "response_invalid_code": null, - "response_invalid_email": null, - "response_email_success": null, - "always_show_info": "Mostrar informações", - "item_not_available": "Item indisponível", - "primary_language": "Língua primaria", - "secondary_language": "Línguas secundárias", - "previous_content": "Conteúdo anterior:", - "followup_content": "Próximo conteúdo:", - "videos": "Videos:", - "view_on_x": "Ver no {x}", - "channel": "Canal", - "subscribers": "Inscritos", - "description": "Descrição", - "available_at_x": "Disponível no {x}", - "want_it": null, - "have_it": null, - "source": null, - "reset_all_filters": null, - "only_display_items_i_have": null, - "only_display_items_i_want": null, - "only_display_unmarked_items": null, - "table_of_contents": null, - "no_results_message": null, - "all": null, - "special_pages": null, - "scan": null, - "scanlation": null, - "scanners": null, - "cleaners": null, - "typesetters": null, - "notes": null, - "tags": null, - "no_source_warning": null, - "copy_anchor_link": null, - "anchor_link_copied": null, - "folders": null, - "empty_folder_message": null, - "switch_to_grid_view": null, - "switch_to_folder_view": null, - "paper_texture": null, - "book_fold": null, - "lighting": null, - "side_pages": null, - "shadow": null, - "night_reader": null, - "single_page_view": null, - "double_page_view": null, - "reset_all_options": null, - "reading_layout": null, - "quality": null, - "only_unavailable_videos": null, - "oldest": null, - "newest": null, - "least_popular": null, - "most_popular": null, - "shortest": null, - "longest": null, - "search": null, - "showing_x_out_of_y_results": null, - "return_to_x": null, - "x_results": null, - "definition_x": null, - "subitem_of_x": null, - "dark_mode_extension_warning": null, - "weapon": null, - "weapons_description": null, - "level_x": null, - "story_x": null, - "player_name_tooltip": null, - "download_archive": null, - "search_placeholder": null, - "performance_mode": null, - "performance_mode_tooltip": null, - "transcriber": null, - "translator": null, - "proofreader": null, - "dubber": null, - "subber": null, - "author": null - } - }, - { - "attributes": { - "ui_language": { "data": { "attributes": { "code": "zh" } } }, - "library": "图书馆", - "contents": "各项内容", - "wiki": "百科", - "chronicles": "年表", - "library_short_description": "查看所有实体媒介和数字媒介", - "contents_short_description": "查找各类内容,包含类型查询及标签查询功能。", - "wiki_short_description": "世界观百科全书", - "chronicles_short_description": "以年表顺序浏览所有事件及内容", - "news": "最新情报", - "gallery": "画廊", - "archives": "档案", - "about_us": "关于本站", - "licensing_notice": "如非特殊声明,本网站将遵循\n[CC-BY-SA](https://creativecommons.org/licenses/by-sa/4.0/)共享协议。", - "copyright_notice": "本网站不属于有限公司史克威尔艾尼克斯,且并未获得相关支持。所有游戏资产及宣传材料均属于\n© SQUARE ENIX CO. LTD.", - "contents_description": "所有内容(文本、音频和视频)均来自图书馆板块及其他网络资源。", - "type": "类目", - "category": "标签", - "size": "尺寸", - "release_date": "发售日", - "details": "详情", - "price": "价格", - "width": "宽", - "height": "高", - "thickness": "厚度", - "subitem": "内容物", - "variant": "各版本", - "summary": "概览", - "audio": "音频", - "video": "视频", - "textual": "文本", - "game": "游戏", - "other": "其他", - "left_to_right": "从左到右", - "right_to_left": "从右到左", - "page": "页数", - "page_order": "阅读顺序", - "binding": "装订类别", - "type_information": "类目信息", - "front_matter": "扉页", - "back_matter": "尾页", - "open_content": "打开", - "view_scans": "查看扫描件", - "paperback": "平装", - "hardcover": "精装", - "language": "语言", - "library_description": "网罗所有横尾世界(Yoko-World)相关资料(书籍、小说、美术集、舞台剧、漫画、广播剧CD以及漫画)。\n我们将尽量为每一项资料提供照片、扫描件及转录文本等内容,并给出物品描述、发售时间及渠道、尺寸与价格等信息。", - "wiki_description": "本版块将收录与横尾世界相关的所有内容。\n当前仅有年表条目,但我们计划在未来添加更多条目。", - "chronicles_description": "以年表顺序浏览所有事件及内容", - "news_description": "这里是网站编辑们书写新闻的板块。\n我们会在这里刊载有关新作/周边发售的消息,还将包含索引、考据、开箱及展会等有关内容。", - "archives_description": "除实体媒介外,我们还将收录网站、网页、视频和文档等内容。", - "about_us_description": "请通过下方页面,了解雅科儿图书馆项目的详细信息。", - "page_not_found": "糟了!这个页面的分歧被暂时封锁了!(404)", - "default_description": "雅科儿图书馆力图收集所有横尾太郎相关作品并归档,\n横尾太郎是一位日本游戏导演兼剧作家。", - "name": "名称", - "show_subitems": "显示内容物", - "show_primary_items": "显示主要商品", - "show_secondary_items": "显示关联商品", - "order_by": "显示顺序", - "select_option_sidebar": "请先在侧边栏进行选择", - "group": null, - "settings": "设置", - "theme": "主题", - "light": "亮", - "auto": "自动", - "dark": "暗", - "font_size": "字号", - "player_name": "玩家名", - "currency": "货币单位", - "font": "字体", - "calculated": "已换算", - "status_incomplete": "该条目仅包含一部分翻译/转写。", - "status_draft": "该条目仅为草稿,一般是指该项目仍在制作当中。翻译或转写质量非常糟糕,甚至可能是机翻和机器识别。", - "status_review": "该页面尚未经过校对,内容有待完善。", - "status_done": "该页面已经过检查和校对,如果你注意到任何翻译或排版的谬误,请联系我们进行修改!", - "incomplete": "未完成", - "draft": "草稿", - "review": "查看", - "done": "完成", - "status": "状态", - "transcript_notice": "转写的内容", - "translation_notice": "该页面为粉丝翻译", - "source_language": "根据 翻译", - "pronouns": "希望被称呼为", - "item": "物品列表", - "open_settings": "打开设置", - "open_search": "打开搜索", - "chronology": "年表", - "accords_handbook": "雅科儿的手册", - "legality": "合法性", - "sharing_policy": "分享守则", - "contact_us": "联系我们", - "email": "电子邮箱", - "email_gdpr_notice": "收集邮箱地址仅用于与您(基于您的请求)进行联络。我们不会将该地址分享给其他人,也不会用与其他目的。", - "message": "留言", - "send": "发送", - "response_invalid_code": "验证码不正确", - "response_invalid_email": "请输入正确的邮箱地址!", - "response_email_success": "感谢您的留言!我们会尽快与您联系。", - "always_show_info": "显示信息", - "item_not_available": "不支持购买", - "primary_language": "主要语言", - "secondary_language": "次要语言", - "previous_content": "{ count, plural, =0 {本文为第一部分} one {上一章节} other {相关章节} }", - "followup_content": "{ count, plural, =0 {本文为最后一部分} one {下一章节} other {后续章节} }", - "videos": "影像", - "view_on_x": "前往 {x} 观看", - "channel": "频道", - "subscribers": "订阅数", - "description": "简介", - "available_at_x": "可在 {x} 查看或购买", - "want_it": "想要!", - "have_it": "已入手!", - "source": "来源", - "reset_all_filters": "重置显示设置", - "only_display_items_i_have": "仅显示我已有的商品", - "only_display_items_i_want": "仅显示我想要的商品", - "only_display_unmarked_items": "仅显示我未添加标签的商品", - "table_of_contents": "目录", - "no_results_message": "未查询到结果,可尝试修改文本或条件。", - "all": "全部", - "special_pages": "特殊页面", - "scan": "扫描方式", - "scanlation": "机器扫描", - "scanners": "扫描者", - "cleaners": "修图", - "typesetters": "转录者", - "notes": "备注", - "tags": "标签", - "no_source_warning": "没有来源!", - "copy_anchor_link": "点击以复制链接", - "anchor_link_copied": "已复制👍", - "folders": "分组", - "empty_folder_message": "该组为空", - "switch_to_grid_view": "切换为网格视图", - "switch_to_folder_view": "切换为分组视图", - "paper_texture": "纸张材质", - "book_fold": "折页效果", - "lighting": "灯光", - "side_pages": "书页厚度效果", - "shadow": "阴影", - "night_reader": "护眼效果", - "single_page_view": "单页模式", - "double_page_view": "跨页模式", - "reset_all_options": "重置所有设置", - "reading_layout": "阅读模式", - "quality": "质量", - "only_unavailable_videos": "显示无法播放的视频", - "oldest": "从旧到新", - "newest": "从新到旧", - "least_popular": "观看数最低", - "most_popular": "观看数最高", - "shortest": "最短的", - "longest": "最长的", - "search": "搜索…", - "showing_x_out_of_y_results": "已显示 {y} 个结果中的 {x}个", - "return_to_x": "返回{ x, select, undefined {} other {{x}} }", - "x_results": "{ x, plural, =0 {没有结果} one {# 个结果} other {# 个结果} }", - "definition_x": "释义 {x}", - "subitem_of_x": "收录于 {x}", - "dark_mode_extension_warning": "本网站支持明亮和黑暗主题,如果你的浏览器被设置为黑暗主题,请将其关闭以确保最佳体验。", - "weapon": "{ count, plural, =0 {没有武器} one {武器} other {武器} }", - "weapons_description": "游戏中登场过的所有武器清单。所有名武器都包含一个专门的页面,里面包含各种细节,包括它们是如何被锻造,过去又是被如何使用的。", - "level_x": "等级 {x}", - "story_x": "故事 {x}", - "player_name_tooltip": "部分游戏中的文本,会在对话和叙事中引用玩家的名字。如果你希望在网站的此类内容中,看到你自己的名字,便可以在这里自由地填写玩家姓名。如果此处留空,则想应文本中会显示“(player)”", - "download_archive": "下载档案", - "search_placeholder": "搜索…", - "performance_mode": "性能模式", - "performance_mode_tooltip": "该选项能够通过减少特效(羽化的背景、阴影等……),以提升您的浏览体验。此模式会在 Linux、iOS 以及 Safari 上默认激活,且无法在 iOS 及 Safari 上关闭此模式,否则体验会非常糟糕。", - "transcriber": "{ count, plural, =0 {无转录者} one {转录者} other {转录者} }", - "translator": "{ count, plural, =0 {无译者} one {译者} other {译者} }", - "proofreader": "{ count, plural, =0 {无校对} one {无校对} other {无校对} }", - "dubber": "{ count, plural, =0 {无配音} one {配音者} other {配音者} }", - "subber": "{ count, plural, =0 {无字幕} one {时间轴} other {时间轴} }", - "author": "{ count, plural, =0 {无作者} one {作者} other {作者} }" - } - } - ] - } -} +{"websiteInterfaces":{"data":[{"attributes":{"ui_language":{"data":{"attributes":{"code":"en"}}},"library":"Library","contents":"Contents","wiki":"Wiki","chronicles":"Chronicles","library_short_description":"Browse all physical and digital media","contents_short_description":"Explore all content and filter by type or category","wiki_short_description":"An encyclopedia for everything related to DrakeNieR","chronicles_short_description":"Experience all events and content in chronological order","news":"News","gallery":"Gallery","archives":"Archives","about_us":"About us","licensing_notice":"This website’s content is made available under [CC-BY-SA](https://creativecommons.org/licenses/by-sa/4.0/) unless otherwise noted.","copyright_notice":"Accord’s Library is not affiliated with or endorsed by SQUARE ENIX CO. LTD. All game assets and promotional materials belongs to © SQUARE ENIX CO. LTD.","contents_description":"All the contents (textual, audio, and video) from the Library or other online sources.","type":"{ count, plural, =0 {No types} one {Type} other {Types} }","category":"{ count, plural, =0 {No categories} one {Category} other {Categories} }","size":"Size","release_date":"Release date","details":"Details","price":"Price","width":"Width","height":"Height","thickness":"Thickness","subitem":"{ count, plural, =0 {No subitems} one {Subitem} other {Subitems} }","variant":"{ count, plural, =0 {No variants} one {Variant} other {Variants} }","summary":"Summary","audio":"Audio","video":"Video","textual":"Textual","game":"Game","other":"Other","left_to_right":"Left to right","right_to_left":"Right to left","page":"{ count, plural, =0 {No pages} one {Page} other {Pages} }","page_order":"Page order","binding":"Binding","type_information":"Type information","front_matter":"Front matter","back_matter":"Back matter","open_content":"Open content","view_scans":"View scans","paperback":"Paperback","hardcover":"Hardcover","language":"{ count, plural, =0 {No languages} one {Language} other {Languages} }","library_description":"A comprehensive list of all Yokoverse’s side materials (books, novellas, artbooks, stage plays, manga, drama CDs, and comics). For each, we provide photos, scans, and transcript of the content, information about what it is, when and how it was released, size, initial price…","wiki_description":"An encyclopedia for everything related to DrakeNieR. Right now, we only have the Chronology but a lot more pages are planned to be released!","chronicles_description":"Experience all events and content in chronological order.","news_description":"News articles written by our Recorders! Here you will find announcements about new merch/items releases, guides, theories, unboxings, showcases...","archives_description":"Besides physical medias, we also archive digital contents such as websites, webpages, videos, and documents.","about_us_description":"Find more information about the Accord's Library project in the following pages.","page_not_found":"Oops! We’re having trouble finding this page","default_description":"Accord's Library aims at gathering and archiving all of Yoko Taro’s work. Yoko Taro is a Japanese video game director and scenario writer.","name":"Name","show_subitems":"Show subitems","show_primary_items":"Show primary items","show_secondary_items":"Show secondary items","order_by":"Order by","select_option_sidebar":"Select one of the options in the sidebar","group":"Group","settings":"Settings","theme":"Theme","light":"Light","auto":"Auto","dark":"Dark","font_size":"Font size","player_name":"Player name","currency":"Currency","font":"Font","calculated":"Calculated","status_incomplete":"This entry is only partially translated/transcribed.","status_draft":"This entry is just a draft. It usually means that this is a work-in-progress. Translation/transcription might be poor and/or computer-generated.","status_review":"This entry has not yet being proofread. The content should still be accurate.","status_done":"This entry has been checked and proofread. If you notice any translation errors or typos, please contact us so we can fix it!","incomplete":"Incomplete","draft":"Draft","review":"Review","done":"Done","status":"Status","transcript_notice":"This content is a transcript","translation_notice":"This content is a fan-translation","source_language":"Source language","pronouns":"Pronouns","item":"{ count, plural, =0 {No items} one {Item} other {Items} }","open_settings":"Open settings","open_search":"Open search","chronology":"Chronology","accords_handbook":"Accord's Handbook","legality":"Legality","sharing_policy":"Sharing Policy","contact_us":"Contact us","email":"Email","email_gdpr_notice":"We only use your email in order to contact you in regard to your request. We do not share this email with anyone nor use it for any other purpose.","message":"Message","send":"Send","response_invalid_code":"Verification code is incorrect.","response_invalid_email":"Please enter a valid email address!","response_email_success":"Thank you for contacting us! We will be in touch with you shortly.","always_show_info":"Always show info","item_not_available":"This item is not for sale or is no longer available","primary_language":"Primary language","secondary_language":"Secondary languages","previous_content":"{ count, plural, =0 {No previous content} one {Previous content} other {Previous contents} }","followup_content":"{ count, plural, =0 {No follow-up content} one {Follow-up content} other {Follow-up contents} }","videos":"Videos","view_on_x":"View on {x}","channel":"Channel","subscribers":"Subscribers","description":"Description","available_at_x":"Available at {x}","want_it":"I want it!","have_it":"I have it!","source":"Source","reset_all_filters":"Reset all filters","only_display_items_i_have":"Only display items marked as “I have”","only_display_items_i_want":"Only display items marked as “I want”","only_display_unmarked_items":"Only display unmarked items","table_of_contents":"Table of Contents","no_results_message":"No results. You can try changing or resetting the search parameters.","all":"All","special_pages":"Special Pages","scan":"Scan","scanlation":"Scanlation","scanners":"Scanners","cleaners":"Cleaners","typesetters":"Typesetters","notes":"Notes","tags":"Tags","no_source_warning":"No source!","copy_anchor_link":"Click to copy the archor link","anchor_link_copied":"Copied! 👍","folders":"Folders","empty_folder_message":"This folder is empty","switch_to_grid_view":"Switch to grid view","switch_to_folder_view":"Switch to folder view","paper_texture":"Paper texture","book_fold":"Book fold","lighting":"Lighting","side_pages":"Side pages","shadow":"Shadow","night_reader":"Night reader","single_page_view":"Single page view","double_page_view":"Double page view","reset_all_options":"Reset all options","reading_layout":"Reading layout","quality":"Quality","only_unavailable_videos":"Only unavailable videos","oldest":"Oldest","newest":"Newest","least_popular":"Least popular","most_popular":"Most popular","shortest":"Shortest","longest":"Longest","search":"Search","showing_x_out_of_y_results":"Showing {x} out of {y} results","return_to_x":"Return { x, select, undefined {} other {to {x}} }","x_results":"{ x, plural, =0 {No results} one {# result} other {# results} }","definition_x":"Definition {x}","subitem_of_x":"Subitem of {x}","dark_mode_extension_warning":"This website offers a light and dark theme. If you are using a \"dark mode\" browser extension, make sure to disable it for an optimal experience.","weapon":"{ count, plural, =0 {No weapons} one {Weapon} other {Weapons} }","weapons_description":"A list of all the weapons across all of the games. All distinguished weapons come with an “account.” It’s a document with various details like how the weapon was forged and how it’s been used in the past.","level_x":"Level {x}","story_x":"Story {x}","player_name_tooltip":"Certain in-game texts use the player's name as part of the dialogue/narration. If you want to see your name in the transcript found on this website, feel free to enter your player's name here. If left empty, '(player)' will be used instead.","download_archive":"Download archive","search_placeholder":"Search...","performance_mode":"Performance mode","performance_mode_tooltip":"This option improves performances by reducing certain visual effects (blurry backgrounds, shadows...). This mode is enabled by default on Linux, iOS, and Safari. This mode cannot be disabled on iOS or Safari as the experience would be too poor.","transcriber":"{ count, plural, =0 {No transcriber} one {Transcriber} other {Transcribers} }","translator":"{ count, plural, =0 {No translator} one {Translator} other {Translators} }","proofreader":"{ count, plural, =0 {No proofreader} one {Proofreader} other {Proofreaders} }","dubber":"{ count, plural, =0 {No dubber} one {Dubber} other {Dubbers} }","subber":"{ count, plural, =0 {No subber} one {Subber} other {Subbers} }","author":"{ count, plural, =0 {No author} one {Author} other {Authors} }"}},{"attributes":{"ui_language":{"data":{"attributes":{"code":"fr"}}},"library":"Bibliothèque","contents":"Contenus","wiki":"Wiki","chronicles":"Chroniques","library_short_description":"Explorer l'ensemble des médias physique ou numérique","contents_short_description":"Explorer tout les contenus et filtrer par type ou par catégorie","wiki_short_description":"Une encyclopédie pour tout l'univers DrakeNieR","chronicles_short_description":"Parcourir tous les événements et les contenu dans l'ordre chronologique","news":"News","gallery":"Galerie","archives":"Archives","about_us":"À propos","licensing_notice":"Le contenu de ce site web est mis à disposition sous licence [CC-BY-SA](https://creativecommons.org/licenses/by-sa/4.0/), sauf indication contraire.","copyright_notice":"Accord's Library n'est pas affiliée ni approuvée par SQUARE ENIX CO. LTD. Tous les contenus du jeu et les contenus promotionnel appartiennent à © SQUARE ENIX CO. LTD.","contents_description":"Tous les contenus (textuels, audio et vidéo) de la Bibliothèque ou d'autres sources en ligne.","type":"{ count, plural, =0 {Pas de type} one {Type} other {Types} }","category":"{ count, plural, =0 {Pas de catégorie} one {Catégorie} other {Catégories} }","size":"Dimension","release_date":"Date de sortie","details":"Détails","price":"Prix","width":"Largeur","height":"Hauteur","thickness":"Épaisseur","subitem":"{ count, plural, =0 {Pas de sous-item} one {Sous-item} other {Sous-items} }","variant":"{ count, plural, =0 {Pas de variante} one {Variante} other {Variantes} }","summary":"Résumé","audio":"Audio","video":"Vidéo","textual":"Textuel","game":"Jeux","other":"Autre","left_to_right":"Gauche à droite","right_to_left":"Droite à gauche","page":"{ count, plural, =0 {Aucune page} one {Page} other {Pages} }","page_order":"Order des pages","binding":"Brochure","type_information":"Information de type","front_matter":"Avant propos","back_matter":"Après propos","open_content":"Parcourir le contenu","view_scans":"Voir les scans","paperback":"Broché","hardcover":"Relié","language":"{ count, plural, =0 {Aucune langue} one {Langue} other {Langues} }","library_description":"Une liste complète de tous les médias annexes du Yokoverse (livres, romans, artbooks, pièces de théâtre, mangas, CD de théâtre et bandes dessinées). Pour chacun, nous fournissons des photos, des scans et une transcription du contenu, des informations sur sa nature, quand il est sorti, sa taille, son prix initial...","wiki_description":"Une encyclopédie pour tout ce qui concerne DrakeNieR. Pour l'instant, nous n'avons que la Chronologie mais beaucoup plus de pages sont prévues !","chronicles_description":"Découvrez tous les événements et contenus de manière chronologique.","news_description":"Articles d'actualité écrits par nos Recorders ! Vous trouverez ici des annonces sur les nouvelles sorties de merch/items, des guides, des théories, des unboxings, des showcases...","archives_description":"Outre les supports physiques, nous archivons également les contenus numériques tels que les sites web, les pages web, les vidéos et les documents.","about_us_description":"Vous trouverez plus d'informations sur le projet Accord's Library dans les pages suivantes.","page_not_found":"Page introuvable","default_description":"Accord's Library a pour but de rassembler et d'archiver l'ensemble des travaux de Yoko Taro. Yoko Taro est un réalisateur et scénariste de jeux vidéo japonais.","name":"Nom","show_subitems":"Afficher les sous-items","show_primary_items":"Afficher les items primaires","show_secondary_items":"Afficher les items secondaires","order_by":"Ordonné par","select_option_sidebar":"Sélectionner l'une des options de la barre latérale","group":"Groupe","settings":"Paramètres","theme":"Thème","light":"Clair","auto":"Auto","dark":"Sombre","font_size":"Taille de la police","player_name":"Nom du joueur","currency":"Devise","font":"Police d'écriture","calculated":"Calculé","status_incomplete":"Cette entrée n'est que partiellement traduite/transcrite.","status_draft":"Cette entrée n'est qu'un brouillon. Cela signifie généralement qu'il s'agit d'un travail en cours. La traduction/transcription peut être médiocre et/ou auto-générée par ordinateur.","status_review":"Cet entrée n'a pas encore été relue. Le contenu devrait néanmoins être correct.","status_done":"Cet entrée a été vérifiée et corrigée. Si vous remarquez des erreurs de traduction ou des fautes de frappe, veuillez nous contacter afin que nous puissions les corriger !","incomplete":"Incomplet","draft":"Ébauche","review":"Pour vérification","done":"Terminé","status":"Statut","transcript_notice":"Ceci est une transcription","translation_notice":"Ceci est une traduction","source_language":"Langue source","pronouns":"Pronoms","item":"{ count, plural, =0 {Aucun item} one {Item} other {Items} }","open_settings":"Ouvrir les paramètres","open_search":"Ouvrir le menu de recherche","chronology":"Chronologie","accords_handbook":"Le manuel de Accord","legality":"Légalité","sharing_policy":"Politique de partage","contact_us":"Nous contacter","email":"Email","email_gdpr_notice":"Nous utilisons votre adresse électronique uniquement pour vous contacter au sujet de votre demande. Nous ne partageons cette adresse avec personne et ne l'utilisons pas à d'autres fins.","message":"Message","send":"Envoyer","response_invalid_code":"Le code de vérification est incorrect.","response_invalid_email":"Veuillez saisir une adresse électronique valide !","response_email_success":"Merci de nous avoir contactés ! Nous prendrons contact avec vous sous peu.","always_show_info":"Toujours montrer les informations","item_not_available":"Cet article n'est pas à vendre ou n'est plus disponible.","primary_language":"Langue principale","secondary_language":"Langues secondaires","previous_content":"Contenu précédent","followup_content":"Contenu suivant","videos":"Videos","view_on_x":"Voir sur {x}","channel":"Chaîne","subscribers":"Abonnés","description":"Description","available_at_x":"Disponible sur {x}","want_it":"Je le veux !","have_it":"Je l'ai !","source":"Source","reset_all_filters":"Réinitialiser les filtres","only_display_items_i_have":"Seulement afficher les items marqués avec \"je le veux\"","only_display_items_i_want":"Seulement afficher les items marqués avec \"je l'ai\"","only_display_unmarked_items":"Seulement afficher les items non-marqués","table_of_contents":"Sommaire","no_results_message":"Aucun résultat. Vous pouvez essayer de modifier ou de réinitialiser les paramètres de recherche.","all":"Tous","special_pages":"Pages spéciales","scan":"Scan","scanlation":"Scantrad","scanners":"Scanneurs","cleaners":"Nettoyeurs","typesetters":"Lettreurs","notes":"Notes","tags":"Tags","no_source_warning":"Pas de source !","copy_anchor_link":"Cliquez pour copier le permalien","anchor_link_copied":"Copié ! 👍","folders":"Dossiers","empty_folder_message":"Ce dossier est vide","switch_to_grid_view":"Vue en grille","switch_to_folder_view":"Vue par dossier","paper_texture":"Texture de papier","book_fold":"Pliure du livre","lighting":"Effet de lumière","side_pages":"Tranche du livre","shadow":"Ombre portée","night_reader":"Mode nuit","single_page_view":"Vue 1 page","double_page_view":"Vue 2 pages","reset_all_options":"Réinitialiser les options","reading_layout":"Mode de lecture","quality":"Qualité","only_unavailable_videos":"Seulement les vidéos indisponibles","oldest":"Plus anciennes","newest":"Plus récentes","least_popular":"Plus populaires","most_popular":"Moins populaires","shortest":"Plus courtes","longest":"Plus longues","search":"Rechercher","showing_x_out_of_y_results":"{x} résultats sur {y} affichés","return_to_x":"Retour { x, select, undefined {} other {à {x}} }","x_results":"{ x, plural, =0 {Pas de résultat} one {# résultat} other {# résultats} }","definition_x":"Définition {x}","subitem_of_x":"Sous-item de {x}","dark_mode_extension_warning":"Ce site web propose un thème clair et un thème sombre. Si vous utilisez une extension de navigateur qui simule un thème sombre, veillez à la désactiver pour une expérience optimale.","weapon":"{ count, plural, =0 {Pas d'arme} one {Arme} other {Armes} }","weapons_description":"Une liste de toutes les armes présentes dans tous les jeux. Toutes les armes distinguées sont accompagnées d'un \"compte\". Il s'agit d'un document contenant divers détails tels que la façon dont l'arme a été forgée et comment elle a été utilisée dans le passé.","level_x":"Niveau {x}","story_x":"Histoire {x}","player_name_tooltip":"Certains textes dans les jeux utilisent le nom du joueur dans les dialogue/la narration. Si vous voulez voir votre nom dans les transcriptions se trouvant sur ce site web, n'hésitez pas à entrer votre nom de joueur ici. S'il n'est pas renseigné, '(player)' sera utilisé à la place.","download_archive":"Télécharger l'archive","search_placeholder":"Rechercher ...","performance_mode":"Mode performance","performance_mode_tooltip":"Cette option permet d'améliorer les performances en réduisant certains effets visuels (flous, ombres...). Ce mode est activé par défaut sur Linux, iOS et Safari. Ce mode ne peut pas être désactivé sur iOS ou Safari car l'expérience serait trop mauvaise.","transcriber":"{ count, plural, =0 {Pas de transcripteur} one {Transcripteur} other {Transcripteurs} }","translator":"{ count, plural, =0 {Pas de traducteur} one {Traducteur} other {Traducteurs} }","proofreader":"{ count, plural, =0 {Pas de correcteur} one {Correcteur} other {Correcteurs} }","dubber":"{ count, plural, =0 {Pas de doubleur} one {Doubleur} other {Doubleurs} }","subber":"{ count, plural, =0 {Pas de sous-titreur} one {Sous-titreur} other {Sous-titreurs} }","author":"{ count, plural, =0 {Pas d'auteur} one {Auteur} other {Auteurs} }"}},{"attributes":{"ui_language":{"data":{"attributes":{"code":"ja"}}},"library":"ライブラリー","contents":"コンテンツ","wiki":"ウィキ","chronicles":"クロニクル","library_short_description":"すべての物理メディアとデジタルメディアを見る","contents_short_description":"すべてのコンテンツを検索し、種類やカテゴリーで絞り込むことができます。","wiki_short_description":"ゲーム宇宙に関連するすべての百科事典です。","chronicles_short_description":"すべてのイベントとコンテンツを時系列で体験できる","news":"ニュース","gallery":"ギャラリー","archives":"アーカイブス","about_us":"会社概要","licensing_notice":"このウェブサイトのコンテンツは、特に断りのない限り [CC-BY-SA](https://creativecommons.org/licenses/by-sa/4.0/) で提供されています。","copyright_notice":"Accord's Libraryは、株式会社スクウェア・エニックスと提携、または推奨しているものではありません。株式会社スクウェア・エニックスの登録商標です。すべてのゲーム資産およびプロモーション素材は、© SQUARE ENIX CO. LTD.に帰属します。","contents_description":"図書館や他のオンラインソースのすべてのコンテンツ(テキスト、オーディオ、ビデオ)。","type":"タイプ","category":"カテゴリー","size":"サイズ","release_date":"発売日","details":"詳細","price":"価格","width":"幅","height":"高さ","thickness":"厚み","subitem":"サブアイテム","variant":"バリアント","summary":"概要","audio":"オーディオ","video":"ビデオ","textual":"テキスト","game":"ゲーム","other":"他","left_to_right":"左から右へ","right_to_left":"右から左へ","page":"ページ","page_order":"ページ順序","binding":"製本","type_information":"タイプ情報","front_matter":"フロントマター","back_matter":"バックナンバー","open_content":"コンテンツを開放","view_scans":"スキャンを開放","paperback":"ペーパーバック","hardcover":"ハードカバー","language":"言語","library_description":"ヨコベースの副教材(書籍、小説、画集、舞台劇、漫画、ドラマCD、コミック)を網羅したリストです。それぞれについて、写真、スキャン、内容の書き起こし、どんなものなのか、いつ、どのように発売されたのか、サイズ、初回価格...などの情報を掲載しています。","wiki_description":"DrakeNieRに関連するすべての百科事典です。現在は年表のみですが、今後多くのページを公開予定です","chronicles_description":"Accord's Libraryは、ヨーコ・タローの全作品を収集・保存することを目的としています。ヨーコ・タローは、日本のゲームディレクター、シナリオライターです。","news_description":"レコーダーが書いたニュース記事です ここでは、新しい商品/アイテムのリリースに関するお知らせ、ガイド、セオリー、アンボックス、ショーケース...をご紹介しています。","archives_description":"","about_us_description":"Accord's Libraryプロジェクトについては、以下のページで詳しくご紹介しています。","page_not_found":"ページが見つかりません","default_description":"Accord's Libraryは、ヨーコ・タローの全作品を収集・保存することを目的としています。ヨーコ・タローは、日本のゲームディレクター、シナリオライターです。","name":"名称","show_subitems":"サブアイテムをみせる","show_primary_items":"一次のイテムをみせる","show_secondary_items":"二次のイテムをみせる","order_by":"注文する","select_option_sidebar":"サイドバーのオプションを選択します","group":"グループ","settings":"設定","theme":"テーマ","light":"光","auto":"オート","dark":"暗","font_size":"文字サイズ","player_name":"プレイヤー名","currency":"通貨","font":"文字","calculated":"計算された","status_incomplete":"このエントリーは一部のみ翻訳/転記されています。","status_draft":"このエントリーはあくまで下書きです。通常、これは作業中であることを意味します。翻訳/転写は稚拙であったり、コンピュータで作成されたものであったりするかもしれません。","status_review":"このエントリーはまだ校正されていません。内容はまだ正確であるはずです。","status_done":"このエントリーは、チェックと校正を行いました。もし、翻訳ミスや誤字脱字にお気づきの際は、修正いたしますので、ご連絡ください","incomplete":"未完成","draft":"ドラフト","review":"レビュー","done":"完了","status":"状況","transcript_notice":"このコンテンツは転写です","translation_notice":"このコンテンツはファンによる翻訳です","source_language":"ソース言語","pronouns":"代名詞","item":"項目","open_settings":"オープン設定","open_search":"オープンサーチ","chronology":"年表","accords_handbook":"アコードの手引き","legality":"合法性","sharing_policy":"共有ポリシー","contact_us":"お問い合わせ","email":"電子メール","email_gdpr_notice":"お客様の電子メールは、お客様のご要望に関してご連絡するためにのみ使用します。この電子メールを誰かと共有したり、他の目的で使用することはありません。","message":"メッセージ","send":"送信","response_invalid_code":"検証コードが正しくありません。","response_invalid_email":"有効なEメールアドレスを入力してください","response_email_success":"お問い合わせありがとうございます。折り返しご連絡させていただきます。","always_show_info":"常に情報を表示する","item_not_available":"この商品は非売品です","primary_language":"主要言語","secondary_language":"二次言語","previous_content":"前のコンテンツ","followup_content":"フォローアップコンテンツ","videos":"動画","view_on_x":null,"channel":"チャンネル","subscribers":"サブスクライバー","description":"説明","available_at_x":null,"want_it":"欲しいです!","have_it":"持ってます!","source":"出典","reset_all_filters":"すべてのフィルタをリセットする","only_display_items_i_have":"\"持ってる \"と表示されているもののみ表示","only_display_items_i_want":"\"欲しい \"とマークされたものだけを表示する","only_display_unmarked_items":"無印のアイテムのみ表示","table_of_contents":"目次","no_results_message":"結果が出ません。検索条件を変更またはリセットしてみてください。","all":"すべて","special_pages":"特設ページ","scan":null,"scanlation":null,"scanners":null,"cleaners":null,"typesetters":null,"notes":null,"tags":null,"no_source_warning":null,"copy_anchor_link":null,"anchor_link_copied":null,"folders":null,"empty_folder_message":null,"switch_to_grid_view":null,"switch_to_folder_view":null,"paper_texture":null,"book_fold":null,"lighting":null,"side_pages":null,"shadow":null,"night_reader":null,"single_page_view":null,"double_page_view":null,"reset_all_options":null,"reading_layout":null,"quality":null,"only_unavailable_videos":null,"oldest":null,"newest":null,"least_popular":null,"most_popular":null,"shortest":null,"longest":null,"search":null,"showing_x_out_of_y_results":null,"return_to_x":null,"x_results":null,"definition_x":null,"subitem_of_x":null,"dark_mode_extension_warning":null,"weapon":null,"weapons_description":null,"level_x":null,"story_x":null,"player_name_tooltip":null,"download_archive":null,"search_placeholder":null,"performance_mode":null,"performance_mode_tooltip":null,"transcriber":null,"translator":null,"proofreader":null,"dubber":null,"subber":null,"author":null}},{"attributes":{"ui_language":{"data":{"attributes":{"code":"es"}}},"library":"Librería","contents":"Contenidos","wiki":"Wiki","chronicles":"Crónicas","library_short_description":"Explora todos los medios físicos y digitales","contents_short_description":"Explora todo el contenido y filtra por tipo o categoría","wiki_short_description":"Una enciclopedia para todo lo relacionado con DrakeNieR","chronicles_short_description":"Experimenta todos los eventos y contenidos en orden cronológico","news":"Novedades","gallery":"Galería","archives":"Archivos","about_us":"Sobre nosotros","licensing_notice":"El contenido de este sitio web está disponible bajo [CC-BY-SA](https://creativecommons.org/licenses/by-sa/4.0/) a menos que se indique lo contrario.","copyright_notice":"Accord's Library no está afiliada ni respaldada por SQUARE ENIX CO. LTD. Todos los archivos de los juegos y material promocional pertenecen a © SQUARE ENIX CO. LTD.","contents_description":"Todo el contenido (textual, audio y video) de la Biblioteca u otras fuentes en línea.","type":"Tipo","category":"Categoría","size":"Tamaño","release_date":"Fecha de lanzamiento","details":"Detalles","price":"Precio","width":"Ancho","height":"Altura","thickness":"Grosor","subitem":"Sub-item","variant":"Variante","summary":"Sumario","audio":"Audio","video":"Video","textual":"Textual","game":"Juego","other":"Otros","left_to_right":"Izquierda a derecha","right_to_left":"Derecha a izquierda","page":"Página","page_order":"Orden de las páginas","binding":"Encuadernación","type_information":"Tipo de información","front_matter":"Anteportada","back_matter":"Portada anterior","open_content":"Abrir contenido","view_scans":"Ver escaneos","paperback":"Tapa blanda","hardcover":"Tapa dura","language":"Idioma","library_description":"Una lista completa de todos los materiales complementarios de Yokoverse (libros, novelas, libros de arte, obras de teatro, manga, CDs novelizados y cómics). Para cada uno, proporcionamos fotos, escaneos y transcripciones del contenido, información sobre qué es, cuándo y cómo se ha publicado, tamaño, precio inicial...","wiki_description":"Una enciclopedia para todo lo relacionado con DrakeNieR. En este momento, solo tenemos la Cronología, ¡pero muchas más páginas están planeadas para ser publicadas!","chronicles_description":"","news_description":"¡Nuevos artículos escritos por nuestros/as Archivistas! Aquí encontrarás anuncios sobre nuevos lanzamientos de merchandising/artículos, guías, teorías, unboxings, showcases...","archives_description":"","about_us_description":"Encuentra más información sobre el proyecto de Accord's Library en las siguientes páginas.","page_not_found":"Página no encontrada","default_description":"Accord's Library tiene como objetivo recopilar y archivar todo el trabajo de Yoko Taro. Yoko Taro es un director de videojuegos y escritor de escenarios japonés.","name":"Nombre","show_subitems":"Mostrar sub-items","show_primary_items":"Mostrar items principales","show_secondary_items":"Mostrar items secundarios","order_by":"Ordenar por","select_option_sidebar":"Selecciona una de las opciones en la barra lateral","group":"Grupo","settings":"Ajustes","theme":"Tema","light":"Claro","auto":"Automático","dark":"Oscuro","font_size":"Tamaño de la fuente","player_name":"Nombre del jugador/a","currency":"Divisa","font":"Fuente","calculated":"Calculada","status_incomplete":"Esta entrada está solo parcialmente traducida/transcrita.","status_draft":"Esta entrada es solo un borrador. Por lo general, significa que se trata de un trabajo en curso. La traducción/transcripción puede ser deficiente y/o generada por ordenador.","status_review":"Esta entrada aún no ha sido corregida. No obstante, el contenido debería ser preciso.","status_done":"Esta entrada ha sido revisada y corregida. Si notas algún error de traducción o error tipográfico, contáctanos para que podamos solucionarlo!","incomplete":"Incompleto","draft":"Borrador","review":"Revisado","done":"Completado","status":"Estado","transcript_notice":"Este contenido es una transcripción","translation_notice":"Este contenido es una traducción de fans","source_language":"Idioma original","pronouns":"Pronombres","item":"Ítem","open_settings":"Abrir ajustes","open_search":"Abrir búsqueda","chronology":"Cronología","accords_handbook":"Manual de Accord","legality":"Legalidad","sharing_policy":"Política de Uso Compartido","contact_us":"Contáctanos","email":"Email","email_gdpr_notice":"Solo usamos tu correo electrónico exclusivamente para contactarte en relación a tu solicitud. No compartimos este correo electrónico con nadie ni lo usamos para ningún otro propósito.","message":"Mensaje","send":"Enviar","response_invalid_code":"El código de verificación es incorrecto.","response_invalid_email":"¡Por favor, introduce una dirección de correo electrónico válida!","response_email_success":"¡Gracias por contactarnos! Nos pondremos en contacto contigo en breve.","always_show_info":"Siempre mostrar la información","item_not_available":"Ítem no disponible","primary_language":"Idioma primario","secondary_language":"Idioma secundario","previous_content":"Contenido anterior","followup_content":"Contenido siguiente","videos":"Vídeos","view_on_x":null,"channel":"Canal","subscribers":"Suscriptores","description":"Descripción","available_at_x":"Disponible en {x}","want_it":"Lo quiero!","have_it":"Lo tengo!","source":"Fuente","reset_all_filters":"Restablecer todos los filtros","only_display_items_i_have":"Sólo mostrar lo que ya tengo","only_display_items_i_want":"Sólo mostrar lo que quiero","only_display_unmarked_items":"Sólo mostrar ítems sin marcación","table_of_contents":"Tabla de contenido","no_results_message":"No hay resultados","all":"Todos","special_pages":"Páginas especiales","scan":"Escaneos","scanlation":"Escaneo/Traducción","scanners":"Escaneadores","cleaners":"Limpiadores","typesetters":"Maquetadores","notes":"Notas","tags":"Etiquetas","no_source_warning":"No hay fuente","copy_anchor_link":"Copiar enlace de anclaje","anchor_link_copied":"Enlace de anclaje copiado","folders":"Carpetas","empty_folder_message":"Carpeta vacía","switch_to_grid_view":"Cambiar a vista de retícula","switch_to_folder_view":"Cambiar a vista de carpeta","paper_texture":"Papel texturizado","book_fold":"Tapa dura","lighting":"Iluminación","side_pages":"Contraportada","shadow":"Sombra","night_reader":"Lector nocturno","single_page_view":"Vista de página única","double_page_view":"Vista de página doble","reset_all_options":"Restablecer todas las opciones","reading_layout":"Disposición de lectura","quality":"Calidad","only_unavailable_videos":null,"oldest":null,"newest":null,"least_popular":null,"most_popular":null,"shortest":null,"longest":null,"search":null,"showing_x_out_of_y_results":null,"return_to_x":null,"x_results":null,"definition_x":null,"subitem_of_x":null,"dark_mode_extension_warning":null,"weapon":null,"weapons_description":null,"level_x":null,"story_x":null,"player_name_tooltip":null,"download_archive":null,"search_placeholder":null,"performance_mode":null,"performance_mode_tooltip":null,"transcriber":null,"translator":null,"proofreader":null,"dubber":null,"subber":null,"author":null}},{"attributes":{"ui_language":{"data":{"attributes":{"code":"pt-br"}}},"library":"Coleção","contents":"Conteúdos","wiki":"Wiki","chronicles":"Crônicas","library_short_description":"Procure por todas mídias digitais e físicas","contents_short_description":"Explore todo o conteúdo e filtre por categorias e tipos","wiki_short_description":"Uma enciclopédia com tudo relacionado a DrakeNieR","chronicles_short_description":"Explore as crônicas de DrakeNieR em ordem cronológica.","news":"Notícias","gallery":"Galeria","archives":"Arquivos","about_us":"Sobre Nós","licensing_notice":"O conteúdo nesse site está disponível pela CC-BY-SA, a não ser que esteja anotado.","copyright_notice":"Accord's Library não é afiliada ou reconhecida pela SQUARE ENIX CO. LTD. Todos assets de jogos e materiais promocionais pertencem a © SQUARE ENIX CO. LTD.\n\n","contents_description":"","type":"Tipo","category":"Categoria","size":"Tamanho","release_date":"Dia de lançamento","details":"Detalhes","price":"Preço","width":"Largura","height":"Altura","thickness":"Grossura","subitem":"Subitem","variant":"Variante","summary":"Sumário","audio":"Audio","video":"Video","textual":"Textos","game":"Jogos","other":"Outros","left_to_right":"Esquerda para direita","right_to_left":"Direita para esquerda","page":"Página","page_order":"Ordem de páginas","binding":"Encadernação","type_information":"Informação do tipo","front_matter":"Pré textual","back_matter":"Pós textual","open_content":"Abrir conteúdo","view_scans":"Ver scans","paperback":"Brochura","hardcover":"Capa dura","language":"Língua","library_description":"","wiki_description":null,"chronicles_description":null,"news_description":"","archives_description":"","about_us_description":"","page_not_found":"Página não encontrada","default_description":null,"name":"Nome","show_subitems":"Mostrar subitens","show_primary_items":"Mostrar itens primários","show_secondary_items":"Mostrar itens secundários","order_by":"Ordenar por","select_option_sidebar":"Selecione uma opção na aba lateral","group":"Grupo","settings":"Configurações","theme":"Tema","light":"Claro","auto":"Automático","dark":"Escuro","font_size":"Tamanho da fonte","player_name":"Nome do jogador","currency":"Moeda","font":"Fonte","calculated":"Calculado","status_incomplete":"Este conteúdo está incompleto e não foi traduzido/transcrito completamente.","status_draft":"A tradução/transcrição selecionada é um Rascunho. Isso significa que a tradução pode estar fraca e/ou ter sido gerada por uma inteligência artificial.","status_review":"Este conteúdo ainda não foi Revisado, erros gramaticais podem ser encontrados uma vez que os revisores ainda não leram a tradução.","status_done":"O conteúdo foi completamente traduzido e revisado.","incomplete":"Incompleto","draft":"Rascunho","review":"Review","done":"Concluido","status":"Status","transcript_notice":"Este conteúdo foi transcrito.","translation_notice":"Este conteúdo é uma tradução de fã.","source_language":"Língua original","pronouns":"Pronomes","item":"Item","open_settings":"Abrir configurações","open_search":"Abrir pesquisa","chronology":"Cronologia","accords_handbook":"Livro de mão da Accord","legality":"Legalidade","sharing_policy":"Política de compartilhamento","contact_us":"Fale conosco","email":null,"email_gdpr_notice":null,"message":null,"send":null,"response_invalid_code":null,"response_invalid_email":null,"response_email_success":null,"always_show_info":"Mostrar informações","item_not_available":"Item indisponível","primary_language":"Língua primaria","secondary_language":"Línguas secundárias","previous_content":"Conteúdo anterior:","followup_content":"Próximo conteúdo:","videos":"Videos:","view_on_x":"Ver no {x}","channel":"Canal","subscribers":"Inscritos","description":"Descrição","available_at_x":"Disponível no {x}","want_it":null,"have_it":null,"source":null,"reset_all_filters":null,"only_display_items_i_have":null,"only_display_items_i_want":null,"only_display_unmarked_items":null,"table_of_contents":null,"no_results_message":null,"all":null,"special_pages":null,"scan":null,"scanlation":null,"scanners":null,"cleaners":null,"typesetters":null,"notes":null,"tags":null,"no_source_warning":null,"copy_anchor_link":null,"anchor_link_copied":null,"folders":null,"empty_folder_message":null,"switch_to_grid_view":null,"switch_to_folder_view":null,"paper_texture":null,"book_fold":null,"lighting":null,"side_pages":null,"shadow":null,"night_reader":null,"single_page_view":null,"double_page_view":null,"reset_all_options":null,"reading_layout":null,"quality":null,"only_unavailable_videos":null,"oldest":null,"newest":null,"least_popular":null,"most_popular":null,"shortest":null,"longest":null,"search":null,"showing_x_out_of_y_results":null,"return_to_x":null,"x_results":null,"definition_x":null,"subitem_of_x":null,"dark_mode_extension_warning":null,"weapon":null,"weapons_description":null,"level_x":null,"story_x":null,"player_name_tooltip":null,"download_archive":null,"search_placeholder":null,"performance_mode":null,"performance_mode_tooltip":null,"transcriber":null,"translator":null,"proofreader":null,"dubber":null,"subber":null,"author":null}},{"attributes":{"ui_language":{"data":{"attributes":{"code":"zh"}}},"library":"图书馆","contents":"各项内容","wiki":"百科","chronicles":"年表","library_short_description":"查看所有实体媒介和数字媒介","contents_short_description":"查找各类内容,包含类型查询及标签查询功能。","wiki_short_description":"世界观百科全书","chronicles_short_description":"以年表顺序浏览所有事件及内容","news":"最新情报","gallery":"画廊","archives":"档案","about_us":"关于本站","licensing_notice":"如非特殊声明,本网站将遵循\n[CC-BY-SA](https://creativecommons.org/licenses/by-sa/4.0/)共享协议。","copyright_notice":"本网站不属于有限公司史克威尔艾尼克斯,且并未获得相关支持。所有游戏资产及宣传材料均属于\n© SQUARE ENIX CO. LTD.","contents_description":"所有内容(文本、音频和视频)均来自图书馆板块及其他网络资源。","type":"类目","category":"标签","size":"尺寸","release_date":"发售日","details":"详情","price":"价格","width":"宽","height":"高","thickness":"厚度","subitem":"内容物","variant":"各版本","summary":"概览","audio":"音频","video":"视频","textual":"文本","game":"游戏","other":"其他","left_to_right":"从左到右","right_to_left":"从右到左","page":"页数","page_order":"阅读顺序","binding":"装订类别","type_information":"类目信息","front_matter":"扉页","back_matter":"尾页","open_content":"打开","view_scans":"查看扫描件","paperback":"平装","hardcover":"精装","language":"语言","library_description":"网罗所有横尾世界(Yoko-World)相关资料(书籍、小说、美术集、舞台剧、漫画、广播剧CD以及漫画)。\n我们将尽量为每一项资料提供照片、扫描件及转录文本等内容,并给出物品描述、发售时间及渠道、尺寸与价格等信息。","wiki_description":"本版块将收录与横尾世界相关的所有内容。\n当前仅有年表条目,但我们计划在未来添加更多条目。","chronicles_description":"以年表顺序浏览所有事件及内容","news_description":"这里是网站编辑们书写新闻的板块。\n我们会在这里刊载有关新作/周边发售的消息,还将包含索引、考据、开箱及展会等有关内容。","archives_description":"除实体媒介外,我们还将收录网站、网页、视频和文档等内容。","about_us_description":"请通过下方页面,了解雅科儿图书馆项目的详细信息。","page_not_found":"糟了!这个页面的分歧被暂时封锁了!(404)","default_description":"雅科儿图书馆力图收集所有横尾太郎相关作品并归档,\n横尾太郎是一位日本游戏导演兼剧作家。","name":"名称","show_subitems":"显示内容物","show_primary_items":"显示主要商品","show_secondary_items":"显示关联商品","order_by":"显示顺序","select_option_sidebar":"请先在侧边栏进行选择","group":null,"settings":"设置","theme":"主题","light":"亮","auto":"自动","dark":"暗","font_size":"字号","player_name":"玩家名","currency":"货币单位","font":"字体","calculated":"已换算","status_incomplete":"该条目仅包含一部分翻译/转写。","status_draft":"该条目仅为草稿,一般是指该项目仍在制作当中。翻译或转写质量非常糟糕,甚至可能是机翻和机器识别。","status_review":"该页面尚未经过校对,内容有待完善。","status_done":"该页面已经过检查和校对,如果你注意到任何翻译或排版的谬误,请联系我们进行修改!","incomplete":"未完成","draft":"草稿","review":"查看","done":"完成","status":"状态","transcript_notice":"转写的内容","translation_notice":"该页面为粉丝翻译","source_language":"根据 翻译","pronouns":"希望被称呼为","item":"物品列表","open_settings":"打开设置","open_search":"打开搜索","chronology":"年表","accords_handbook":"雅科儿的手册","legality":"合法性","sharing_policy":"分享守则","contact_us":"联系我们","email":"电子邮箱","email_gdpr_notice":"收集邮箱地址仅用于与您(基于您的请求)进行联络。我们不会将该地址分享给其他人,也不会用与其他目的。","message":"留言","send":"发送","response_invalid_code":"验证码不正确","response_invalid_email":"请输入正确的邮箱地址!","response_email_success":"感谢您的留言!我们会尽快与您联系。","always_show_info":"显示信息","item_not_available":"不支持购买","primary_language":"主要语言","secondary_language":"次要语言","previous_content":"{ count, plural, =0 {本文为第一部分} one {上一章节} other {相关章节} }","followup_content":"{ count, plural, =0 {本文为最后一部分} one {下一章节} other {后续章节} }","videos":"影像","view_on_x":"前往 {x} 观看","channel":"频道","subscribers":"订阅数","description":"简介","available_at_x":"可在 {x} 查看或购买","want_it":"想要!","have_it":"已入手!","source":"来源","reset_all_filters":"重置显示设置","only_display_items_i_have":"仅显示我已有的商品","only_display_items_i_want":"仅显示我想要的商品","only_display_unmarked_items":"仅显示我未添加标签的商品","table_of_contents":"目录","no_results_message":"未查询到结果,可尝试修改文本或条件。","all":"全部","special_pages":"特殊页面","scan":"扫描方式","scanlation":"机器扫描","scanners":"扫描者","cleaners":"修图","typesetters":"转录者","notes":"备注","tags":"标签","no_source_warning":"没有来源!","copy_anchor_link":"点击以复制链接","anchor_link_copied":"已复制👍","folders":"分组","empty_folder_message":"该组为空","switch_to_grid_view":"切换为网格视图","switch_to_folder_view":"切换为分组视图","paper_texture":"纸张材质","book_fold":"折页效果","lighting":"灯光","side_pages":"书页厚度效果","shadow":"阴影","night_reader":"护眼效果","single_page_view":"单页模式","double_page_view":"跨页模式","reset_all_options":"重置所有设置","reading_layout":"阅读模式","quality":"质量","only_unavailable_videos":"显示无法播放的视频","oldest":"从旧到新","newest":"从新到旧","least_popular":"观看数最低","most_popular":"观看数最高","shortest":"最短的","longest":"最长的","search":"搜索…","showing_x_out_of_y_results":"已显示 {y} 个结果中的 {x}个","return_to_x":"返回{ x, select, undefined {} other {{x}} }","x_results":"{ x, plural, =0 {没有结果} one {# 个结果} other {# 个结果} }","definition_x":"释义 {x}","subitem_of_x":"收录于 {x}","dark_mode_extension_warning":"本网站支持明亮和黑暗主题,如果你的浏览器被设置为黑暗主题,请将其关闭以确保最佳体验。","weapon":"{ count, plural, =0 {没有武器} one {武器} other {武器} }","weapons_description":"游戏中登场过的所有武器清单。所有名武器都包含一个专门的页面,里面包含各种细节,包括它们是如何被锻造,过去又是被如何使用的。","level_x":"等级 {x}","story_x":"故事 {x}","player_name_tooltip":"部分游戏中的文本,会在对话和叙事中引用玩家的名字。如果你希望在网站的此类内容中,看到你自己的名字,便可以在这里自由地填写玩家姓名。如果此处留空,则想应文本中会显示“(player)”","download_archive":"下载档案","search_placeholder":"搜索…","performance_mode":"性能模式","performance_mode_tooltip":"该选项能够通过减少特效(羽化的背景、阴影等……),以提升您的浏览体验。此模式会在 Linux、iOS 以及 Safari 上默认激活,且无法在 iOS 及 Safari 上关闭此模式,否则体验会非常糟糕。","transcriber":"{ count, plural, =0 {无转录者} one {转录者} other {转录者} }","translator":"{ count, plural, =0 {无译者} one {译者} other {译者} }","proofreader":"{ count, plural, =0 {无校对} one {无校对} other {无校对} }","dubber":"{ count, plural, =0 {无配音} one {配音者} other {配音者} }","subber":"{ count, plural, =0 {无字幕} one {时间轴} other {时间轴} }","author":"{ count, plural, =0 {无作者} one {作者} other {作者} }"}}]}} \ No newline at end of file diff --git a/src/components/Credits.tsx b/src/components/Credits.tsx index ea0ca3d..66a35fe 100644 --- a/src/components/Credits.tsx +++ b/src/components/Credits.tsx @@ -3,7 +3,6 @@ import { Markdawn } from "components/Markdown/Markdawn"; import { RecorderChip } from "components/RecorderChip"; import { ToolTip } from "components/ToolTip"; import { atoms } from "contexts/atoms"; -import { RecorderChipFragment } from "graphql/generated"; import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts"; import { useAtomGetter } from "helpers/atoms"; import { prettyLanguage } from "helpers/formatters"; @@ -18,12 +17,12 @@ interface Props { languageCode?: string; sourceLanguageCode?: string; status?: ContentStatus | null; - transcribers?: { attributes?: RecorderChipFragment | null }[]; - translators?: { attributes?: RecorderChipFragment | null }[]; - proofreaders?: { attributes?: RecorderChipFragment | null }[]; - dubbers?: { attributes?: RecorderChipFragment | null }[]; - subbers?: { attributes?: RecorderChipFragment | null }[]; - authors?: { attributes?: RecorderChipFragment | null }[]; + transcribers?: RecorderChipsProps["recorders"]; + translators?: RecorderChipsProps["recorders"]; + proofreaders?: RecorderChipsProps["recorders"]; + dubbers?: RecorderChipsProps["recorders"]; + subbers?: RecorderChipsProps["recorders"]; + authors?: RecorderChipsProps["recorders"]; notes?: string | null; } @@ -118,14 +117,14 @@ export const Credits = ({ interface RecorderChipsProps { title: string; - recorders: { attributes?: RecorderChipFragment | null }[]; + recorders: { attributes?: { username: string } | null }[]; } const RecorderChips = ({ title, recorders }: RecorderChipsProps) => (

{title}:

{filterHasAttributes(recorders, ["attributes"]).map((recorder) => ( - + ))}
); diff --git a/src/components/Panels/SearchPopup.tsx b/src/components/Panels/SearchPopup.tsx index 01e37d0..2017896 100644 --- a/src/components/Panels/SearchPopup.tsx +++ b/src/components/Panels/SearchPopup.tsx @@ -24,7 +24,7 @@ import { } from "shared/meilisearch-graphql-typings/meiliTypes"; import { getVideoThumbnailURL } from "helpers/videos"; import { UpPressable } from "components/Containers/UpPressable"; -import { prettyItemSubType, prettySlug } from "helpers/formatters"; +import { prettySlug } from "helpers/formatters"; import { Ico } from "components/Ico"; import { useFormat } from "hooks/useFormat"; @@ -52,7 +52,14 @@ interface MultiResult { export const SearchPopup = (): JSX.Element => { const [isSearchOpened, setSearchOpened] = useAtomPair(atoms.layout.searchOpened); const [query, setQuery] = useState(""); - const { format } = useFormat(); + const { + format, + formatCategory, + formatContentType, + formatWikiTag, + formatLibraryItemSubType, + formatWeaponType, + } = useFormat(); const [multiResult, setMultiResult] = useState({}); const fetchSearchResults = useCallback((q: string) => { @@ -243,11 +250,11 @@ export const SearchPopup = (): JSX.Element => { keepInfoVisible topChips={ item.metadata && item.metadata.length > 0 && item.metadata[0] - ? [prettyItemSubType(item.metadata[0])] + ? [formatLibraryItemSubType(item.metadata[0])] : [] } - bottomChips={item.categories?.data.map( - (category) => category.attributes?.short ?? "" + bottomChips={filterHasAttributes(item.categories?.data, ["attributes"]).map( + (category) => formatCategory(category.attributes.slug) )} metadata={{ releaseDate: item.release_date, @@ -288,15 +295,11 @@ export const SearchPopup = (): JSX.Element => { thumbnailForceAspectRatio topChips={ item.type?.data?.attributes - ? [ - item.type.data.attributes.titles?.[0] - ? item.type.data.attributes.titles[0]?.title - : prettySlug(item.type.data.attributes.slug), - ] + ? [formatContentType(item.type.data.attributes.slug)] : undefined } - bottomChips={item.categories?.data.map( - (category) => category.attributes?.short ?? "" + bottomChips={filterHasAttributes(item.categories?.data, ["attributes"]).map( + (category) => formatCategory(category.attributes.slug) )} keepInfoVisible /> @@ -345,11 +348,11 @@ export const SearchPopup = (): JSX.Element => { thumbnailRounded thumbnailForceAspectRatio keepInfoVisible - topChips={filterHasAttributes(item.tags?.data, ["attributes"]).map( - (tag) => tag.attributes.titles?.[0]?.title ?? prettySlug(tag.attributes.slug) + topChips={filterHasAttributes(item.tags?.data, ["attributes"]).map((tag) => + formatWikiTag(tag.attributes.slug) )} bottomChips={filterHasAttributes(item.categories?.data, ["attributes"]).map( - (category) => category.attributes.short + (category) => formatCategory(category.attributes.slug) )} /> ))} @@ -384,8 +387,8 @@ export const SearchPopup = (): JSX.Element => { thumbnailAspectRatio="3/2" thumbnailForceAspectRatio keepInfoVisible - bottomChips={item.categories?.data.map( - (category) => category.attributes?.short ?? "" + bottomChips={filterHasAttributes(item.categories?.data, ["attributes"]).map( + (category) => formatCategory(category.attributes.slug) )} metadata={{ releaseDate: item.date, @@ -466,11 +469,11 @@ export const SearchPopup = (): JSX.Element => { keepInfoVisible topChips={ item.type?.data?.attributes?.slug - ? [prettySlug(item.type.data.attributes.slug)] + ? [formatWeaponType(item.type.data.attributes.slug)] : undefined } - bottomChips={filterHasAttributes(item.categories, ["attributes.short"]).map( - (category) => category.attributes.short + bottomChips={filterHasAttributes(item.categories, ["attributes"]).map( + (category) => formatCategory(category.attributes.slug) )} /> ))} diff --git a/src/components/PostPage.tsx b/src/components/PostPage.tsx index d329fd9..02e8f74 100644 --- a/src/components/PostPage.tsx +++ b/src/components/PostPage.tsx @@ -7,13 +7,14 @@ import { SubPanel } from "./Containers/SubPanel"; import { ThumbnailHeader } from "./ThumbnailHeader"; import { useSmartLanguage } from "hooks/useSmartLanguage"; import { PostWithTranslations } from "types/types"; -import { isDefined } from "helpers/asserts"; +import { filterHasAttributes, isDefined } from "helpers/asserts"; import { prettySlug } from "helpers/formatters"; import { useAtomGetter, useAtomSetter } from "helpers/atoms"; import { atoms } from "contexts/atoms"; import { ElementsSeparator } from "helpers/component"; import { HorizontalLine } from "components/HorizontalLine"; import { Credits } from "components/Credits"; +import { useFormat } from "hooks/useFormat"; /* * ╭─────────────╮ @@ -48,6 +49,7 @@ export const PostPage = ({ displayTitle = true, ...otherProps }: Props): JSX.Element => { + const { formatCategory } = useFormat(); const setSubPanelOpened = useAtomSetter(atoms.layout.subPanelOpened); const is1ColumnLayout = useAtomGetter(atoms.containerQueries.is1ColumnLayout); @@ -104,7 +106,9 @@ export const PostPage = ({ thumbnail={thumbnail} title={title} description={excerpt} - categories={post.categories} + categories={filterHasAttributes(post.categories?.data, ["attributes"]).map((category) => + formatCategory(category.attributes.slug) + )} languageSwitcher={ languageSwitcherProps.locales.size > 1 ? ( diff --git a/src/components/RecorderChip.tsx b/src/components/RecorderChip.tsx index d17cda2..db07eb4 100644 --- a/src/components/RecorderChip.tsx +++ b/src/components/RecorderChip.tsx @@ -3,10 +3,12 @@ import { Img } from "./Img"; import { Markdawn } from "./Markdown/Markdawn"; import { ToolTip } from "./ToolTip"; import { Chip } from "components/Chip"; -import { RecorderChipFragment } from "graphql/generated"; import { ImageQuality } from "helpers/img"; -import { filterHasAttributes } from "helpers/asserts"; +import { filterHasAttributes, isUndefined } from "helpers/asserts"; import { useFormat } from "hooks/useFormat"; +import { useAtomGetter } from "helpers/atoms"; +import { atoms } from "contexts/atoms"; +import { useSmartLanguage } from "hooks/useSmartLanguage"; /* * ╭─────────────╮ @@ -14,14 +16,22 @@ import { useFormat } from "hooks/useFormat"; */ interface Props { - className?: string; - recorder: RecorderChipFragment; + username: string; } // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ -export const RecorderChip = ({ recorder }: Props): JSX.Element => { +export const RecorderChip = ({ username }: Props): JSX.Element => { const { format } = useFormat(); + const recorders = useAtomGetter(atoms.localData.recorders); + const recorder = recorders.find((elem) => elem.attributes?.username === username)?.attributes; + + const [selectedBioTranslation] = useSmartLanguage({ + items: recorder?.bio ?? [], + languageExtractor: (bio) => bio.language?.data?.attributes?.code, + }); + + if (isUndefined(recorder)) return <>; return ( { )} - {recorder.bio?.[0] && } + {selectedBioTranslation?.bio && } } placement="top"> diff --git a/src/components/ThumbnailHeader.tsx b/src/components/ThumbnailHeader.tsx index 2a6f1c2..9e3b403 100644 --- a/src/components/ThumbnailHeader.tsx +++ b/src/components/ThumbnailHeader.tsx @@ -2,10 +2,9 @@ import { Chip } from "components/Chip"; import { Img } from "components/Img"; import { InsetBox } from "components/Containers/InsetBox"; import { Markdawn } from "components/Markdown/Markdawn"; -import { GetContentTextQuery, UploadImageFragment } from "graphql/generated"; -import { prettyInlineTitle, prettySlug, slugify } from "helpers/formatters"; +import { UploadImageFragment } from "graphql/generated"; +import { prettyInlineTitle, slugify } from "helpers/formatters"; import { ImageQuality } from "helpers/img"; -import { filterHasAttributes } from "helpers/asserts"; import { useAtomGetter } from "helpers/atoms"; import { atoms } from "contexts/atoms"; import { useFormat } from "hooks/useFormat"; @@ -20,12 +19,8 @@ interface Props { title: string | null | undefined; subtitle?: string | null | undefined; description?: string | null | undefined; - type?: NonNullable< - NonNullable["data"][number]["attributes"] - >["type"]; - categories?: NonNullable< - NonNullable["data"][number]["attributes"] - >["categories"]; + type?: string; + categories?: string[]; thumbnail?: UploadImageFragment | null | undefined; className?: string; languageSwitcher?: JSX.Element; @@ -72,25 +67,21 @@ export const ThumbnailHeader = ({
- {type?.data?.attributes && ( + {type && (

{format("type", { count: 1 })}

- +
)} - {categories && categories.data.length > 0 && ( + {categories && categories.length > 0 && (
-

{format("category", { count: categories.data.length })}

+

{format("category", { count: categories.length })}

- {filterHasAttributes(categories.data, ["attributes", "id"]).map((category) => ( - + {categories.map((category) => ( + ))}
diff --git a/src/contexts/atoms.ts b/src/contexts/atoms.ts index ea89816..f6666ff 100644 --- a/src/contexts/atoms.ts +++ b/src/contexts/atoms.ts @@ -5,7 +5,7 @@ import { userAgent } from "contexts/userAgent"; import { atomPairing } from "helpers/atoms"; import { settings } from "contexts/settings"; import { UploadImageFragment } from "graphql/generated"; -import { Languages, Currencies, Langui } from "helpers/localData"; +import { Languages, Currencies, Langui, Recorders, TypesTranslations } from "helpers/localData"; /* [ LOCAL DATA ATOMS ] */ @@ -13,12 +13,29 @@ const languages = atomPairing(atom([])); const currencies = atomPairing(atom([])); const langui = atomPairing(atom({})); const fallbackLangui = atomPairing(atom({})); +const recorders = atomPairing(atom([])); +const typesTranslations = atomPairing( + atom({ + audioSubtypes: [], + categories: [], + contentTypes: [], + gamePlatforms: [], + groupSubtypes: [], + metadataTypes: [], + textualSubtypes: [], + videoSubtypes: [], + wikiPagesTags: [], + weaponTypes: [], + }) +); const localData = { languages: languages[0], currencies: currencies[0], langui: langui[0], fallbackLangui: fallbackLangui[0], + recorders: recorders[0], + typesTranslations: typesTranslations[0], }; /* [ LIGHTBOX ATOMS ] */ @@ -70,5 +87,5 @@ export const atoms = { // Do not import outside of the "contexts" folder export const internalAtoms = { lightBox: lightBoxAtom, - localData: { languages, currencies, langui, fallbackLangui }, + localData: { languages, currencies, langui, fallbackLangui, recorders, typesTranslations }, }; diff --git a/src/contexts/localData.ts b/src/contexts/localData.ts index cd9f5d2..4c32286 100644 --- a/src/contexts/localData.ts +++ b/src/contexts/localData.ts @@ -7,10 +7,17 @@ import { LocalDataGetWebsiteInterfacesQuery, LocalDataGetCurrenciesQuery, LocalDataGetLanguagesQuery, + LocalDataGetRecordersQuery, } from "graphql/generated"; import { LocalDataFile } from "graphql/fetchLocalData"; import { internalAtoms } from "contexts/atoms"; -import { processLanguages, processCurrencies, processLangui } from "helpers/localData"; +import { + processLanguages, + processCurrencies, + processLangui, + processRecorders, + processTypesTranslations, +} from "helpers/localData"; import { getLogger } from "helpers/logger"; const getFileName = (name: LocalDataFile): string => `/local-data/${name}.json`; @@ -21,6 +28,8 @@ export const useLocalData = (): void => { const setCurrencies = useAtomSetter(internalAtoms.localData.currencies); const setLangui = useAtomSetter(internalAtoms.localData.langui); const setFallbackLangui = useAtomSetter(internalAtoms.localData.fallbackLangui); + const setRecorders = useAtomSetter(internalAtoms.localData.recorders); + const setTypesTranslations = useAtomSetter(internalAtoms.localData.typesTranslations); const { locale } = useRouter(); const { data: rawLanguages } = useFetch(getFileName("languages")); @@ -28,6 +37,10 @@ export const useLocalData = (): void => { const { data: rawLangui } = useFetch( getFileName("websiteInterfaces") ); + const { data: rawRecorders } = useFetch(getFileName("recorders")); + const { data: rawTypesTranslations } = useFetch( + getFileName("typesTranslations") + ); useEffect(() => { logger.log("Refresh languages"); @@ -48,4 +61,14 @@ export const useLocalData = (): void => { logger.log("Refresh fallback langui"); setFallbackLangui(processLangui(rawLangui, "en")); }, [rawLangui, setFallbackLangui]); + + useEffect(() => { + logger.log("Refresh recorders"); + setRecorders(processRecorders(rawRecorders)); + }, [rawRecorders, setRecorders]); + + useEffect(() => { + logger.log("Refresh types translations"); + setTypesTranslations(processTypesTranslations(rawTypesTranslations)); + }, [rawTypesTranslations, setTypesTranslations]); }; diff --git a/src/graphql/fetchLocalData.ts b/src/graphql/fetchLocalData.ts index e5451b2..9937503 100644 --- a/src/graphql/fetchLocalData.ts +++ b/src/graphql/fetchLocalData.ts @@ -3,8 +3,16 @@ import { resolve } from "path"; import { readFileSync, writeFileSync } from "fs"; import { config } from "dotenv"; import { getReadySdk } from "./sdk"; -import { LocalDataGetWebsiteInterfacesQuery } from "./generated"; -import { processLangui, Langui } from "helpers/localData"; +import { + LocalDataGetTypesTranslationsQuery, + LocalDataGetWebsiteInterfacesQuery, +} from "./generated"; +import { + processLangui, + Langui, + TypesTranslations, + processTypesTranslations, +} from "helpers/localData"; import { getLogger } from "helpers/logger"; config({ path: resolve(process.cwd(), ".env.local") }); @@ -12,7 +20,7 @@ config({ path: resolve(process.cwd(), ".env.local") }); const LOCAL_DATA_FOLDER = `${process.cwd()}/public/local-data`; const logger = getLogger("💽 [Local Data]", "server"); -const writeLocalData = (name: LocalDataFile, localData: unknown) => { +const writeLocalData = (name: LocalDataFile, localData: object) => { const path = `${LOCAL_DATA_FOLDER}/${name}.json`; writeFileSync(path, JSON.stringify(localData), { encoding: "utf-8" }); logger.log(`${name}.json has been written`); @@ -23,22 +31,58 @@ const readLocalData = (name: LocalDataFile): T => { return JSON.parse(readFileSync(path, { encoding: "utf8" })); }; -export const fetchLocalData = async (): Promise => { +export const fetchWebsiteInterfaces = async (): Promise => { const sdk = getReadySdk(); writeLocalData("websiteInterfaces", await sdk.localDataGetWebsiteInterfaces()); +}; + +export const fetchCurrencies = async (): Promise => { + const sdk = getReadySdk(); writeLocalData("currencies", await sdk.localDataGetCurrencies()); +}; + +export const fetchLanguages = async (): Promise => { + const sdk = getReadySdk(); writeLocalData("languages", await sdk.localDataGetLanguages()); }; +export const fetchRecorders = async (): Promise => { + const sdk = getReadySdk(); + writeLocalData("recorders", await sdk.localDataGetRecorders()); +}; + +export const fetchTypesTranslations = async (): Promise => { + const sdk = getReadySdk(); + writeLocalData("typesTranslations", await sdk.localDataGetTypesTranslations()); +}; + +const fetchLocalData = async (): Promise => { + await fetchWebsiteInterfaces(); + await fetchCurrencies(); + await fetchLanguages(); + await fetchRecorders(); + await fetchTypesTranslations(); +}; + if (process.argv[2] === "--esrun") { fetchLocalData(); } // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ -export type LocalDataFile = "currencies" | "languages" | "websiteInterfaces"; +export type LocalDataFile = + | "currencies" + | "languages" + | "recorders" + | "typesTranslations" + | "websiteInterfaces"; -export const getLangui = (locale: string | undefined): Langui => { +export const getLangui = (locale: string): Langui => { const websiteInterfaces = readLocalData("websiteInterfaces"); return processLangui(websiteInterfaces, locale); }; + +export const getTypesTranslations = (): TypesTranslations => { + const typesTranslations = readLocalData("typesTranslations"); + return processTypesTranslations(typesTranslations); +}; diff --git a/src/graphql/fragments/recorderChip.graphql b/src/graphql/fragments/recorderChip.graphql deleted file mode 100644 index 8255a81..0000000 --- a/src/graphql/fragments/recorderChip.graphql +++ /dev/null @@ -1,23 +0,0 @@ -fragment recorderChip on Recorder { - username - anonymize - anonymous_code - pronouns - bio(filters: { language: { code: { eq: $language_code } } }) { - bio - } - languages(pagination: { limit: -1 }) { - data { - attributes { - code - } - } - } - avatar { - data { - attributes { - ...uploadImage - } - } - } -} diff --git a/src/graphql/fragments/relatedContentPreview.graphql b/src/graphql/fragments/relatedContentPreview.graphql index 4727b8b..62245be 100644 --- a/src/graphql/fragments/relatedContentPreview.graphql +++ b/src/graphql/fragments/relatedContentPreview.graphql @@ -14,9 +14,8 @@ fragment relatedContentPreview on Content { } categories(pagination: { limit: -1 }) { data { - id attributes { - short + slug } } } @@ -24,9 +23,6 @@ fragment relatedContentPreview on Content { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } diff --git a/src/graphql/getPostStaticProps.ts b/src/graphql/getPostStaticProps.ts index 14e462a..398c643 100644 --- a/src/graphql/getPostStaticProps.ts +++ b/src/graphql/getPostStaticProps.ts @@ -17,10 +17,9 @@ export const getPostStaticProps = (slug: string): GetStaticProps => async (context) => { const sdk = getReadySdk(); - const { format } = getFormat(context.locale); + const { format, formatCategory } = getFormat(context.locale); const post = await sdk.getPost({ slug: slug, - language_code: context.locale ?? "en", }); if (!post.posts?.data[0]?.attributes?.translations || !context.locale || !context.locales) { @@ -40,7 +39,7 @@ export const getPostStaticProps = [format("category", { count: Infinity })]: filterHasAttributes( post.posts.data[0].attributes.categories?.data, ["attributes"] - ).map((category) => category.attributes.short), + ).map((category) => formatCategory(category.attributes.slug)), }); const thumbnail = diff --git a/src/graphql/operations/getChronicle.graphql b/src/graphql/operations/getChronicle.graphql index 2f78a6e..a1ec2ea 100644 --- a/src/graphql/operations/getChronicle.graphql +++ b/src/graphql/operations/getChronicle.graphql @@ -1,4 +1,4 @@ -query getChronicle($slug: String, $language_code: String) { +query getChronicle($slug: String) { chronicles(filters: { slug: { eq: $slug } }) { data { attributes { @@ -53,21 +53,21 @@ query getChronicle($slug: String, $language_code: String) { authors { data { attributes { - ...recorderChip + username } } } translators { data { attributes { - ...recorderChip + username } } } proofreaders { data { attributes { - ...recorderChip + username } } } @@ -80,10 +80,8 @@ query getChronicle($slug: String, $language_code: String) { slug categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -91,9 +89,6 @@ query getChronicle($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -123,7 +118,7 @@ query getChronicle($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -131,7 +126,7 @@ query getChronicle($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -139,7 +134,7 @@ query getChronicle($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } diff --git a/src/graphql/operations/getContentText.graphql b/src/graphql/operations/getContentText.graphql index 868136b..4707216 100644 --- a/src/graphql/operations/getContentText.graphql +++ b/src/graphql/operations/getContentText.graphql @@ -1,4 +1,4 @@ -query getContentText($slug: String, $language_code: String) { +query getContentText($slug: String) { contents(filters: { slug: { eq: $slug } }) { data { id @@ -6,10 +6,8 @@ query getContentText($slug: String, $language_code: String) { slug categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -17,9 +15,6 @@ query getContentText($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -53,10 +48,8 @@ query getContentText($slug: String, $language_code: String) { } categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -67,19 +60,15 @@ query getContentText($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } } ... on ComponentMetadataGame { - platforms(pagination: { limit: -1 }) { + platform { data { - id attributes { - short + slug } } } @@ -89,9 +78,6 @@ query getContentText($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -101,9 +87,6 @@ query getContentText($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -113,9 +96,6 @@ query getContentText($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -123,9 +103,6 @@ query getContentText($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -163,7 +140,7 @@ query getContentText($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -171,7 +148,7 @@ query getContentText($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -179,7 +156,7 @@ query getContentText($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -198,7 +175,7 @@ query getContentText($slug: String, $language_code: String) { subbers(pagination: { limit: -1 }) { data { attributes { - ...recorderChip + username } } } @@ -216,7 +193,7 @@ query getContentText($slug: String, $language_code: String) { dubbers(pagination: { limit: -1 }) { data { attributes { - ...recorderChip + username } } } diff --git a/src/graphql/operations/getContentsFolder.graphql b/src/graphql/operations/getContentsFolder.graphql index fdbf776..e656827 100644 --- a/src/graphql/operations/getContentsFolder.graphql +++ b/src/graphql/operations/getContentsFolder.graphql @@ -1,4 +1,4 @@ -query getContentsFolder($slug: String, $language_code: String) { +query getContentsFolder($slug: String) { contentsFolders(filters: { slug: { eq: $slug } }) { data { attributes { @@ -22,10 +22,8 @@ query getContentsFolder($slug: String, $language_code: String) { } categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -33,9 +31,6 @@ query getContentsFolder($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } diff --git a/src/graphql/operations/getLibraryItem.graphql b/src/graphql/operations/getLibraryItem.graphql index 69b8e4b..871fd8a 100644 --- a/src/graphql/operations/getLibraryItem.graphql +++ b/src/graphql/operations/getLibraryItem.graphql @@ -1,4 +1,4 @@ -query getLibraryItem($slug: String, $language_code: String) { +query getLibraryItem($slug: String) { libraryItems(filters: { slug: { eq: $slug } }) { data { id @@ -33,10 +33,8 @@ query getLibraryItem($slug: String, $language_code: String) { } categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -58,9 +56,6 @@ query getLibraryItem($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -81,19 +76,15 @@ query getLibraryItem($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } } ... on ComponentMetadataGame { - platforms(pagination: { limit: -1 }) { + platform { data { - id attributes { - short + slug } } } @@ -127,9 +118,6 @@ query getLibraryItem($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -144,9 +132,6 @@ query getLibraryItem($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -154,9 +139,6 @@ query getLibraryItem($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -194,10 +176,8 @@ query getLibraryItem($slug: String, $language_code: String) { } categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -208,19 +188,16 @@ query getLibraryItem($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } } ... on ComponentMetadataGame { - platforms { + platform { data { id attributes { - short + slug } } } @@ -230,9 +207,6 @@ query getLibraryItem($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -242,9 +216,6 @@ query getLibraryItem($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -254,9 +225,6 @@ query getLibraryItem($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -264,9 +232,6 @@ query getLibraryItem($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -317,10 +282,8 @@ query getLibraryItem($slug: String, $language_code: String) { slug categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -328,9 +291,6 @@ query getLibraryItem($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } diff --git a/src/graphql/operations/getLibraryItemScans.graphql b/src/graphql/operations/getLibraryItemScans.graphql index 0ba2a22..9a8c0e4 100644 --- a/src/graphql/operations/getLibraryItemScans.graphql +++ b/src/graphql/operations/getLibraryItemScans.graphql @@ -1,4 +1,4 @@ -query getLibraryItemScans($slug: String, $language_code: String) { +query getLibraryItemScans($slug: String) { libraryItems(filters: { slug: { eq: $slug } }) { data { id @@ -27,7 +27,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -35,7 +35,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -43,7 +43,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -156,10 +156,8 @@ query getLibraryItemScans($slug: String, $language_code: String) { } categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -171,19 +169,16 @@ query getLibraryItemScans($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } } ... on ComponentMetadataGame { - platforms { + platform { data { id attributes { - short + slug } } } @@ -193,9 +188,6 @@ query getLibraryItemScans($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -205,9 +197,6 @@ query getLibraryItemScans($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -217,9 +206,6 @@ query getLibraryItemScans($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -227,9 +213,6 @@ query getLibraryItemScans($slug: String, $language_code: String) { data { attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -290,7 +273,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -298,7 +281,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -306,7 +289,7 @@ query getLibraryItemScans($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } diff --git a/src/graphql/operations/getPost.graphql b/src/graphql/operations/getPost.graphql index 7bd861a..e01a33b 100644 --- a/src/graphql/operations/getPost.graphql +++ b/src/graphql/operations/getPost.graphql @@ -1,4 +1,4 @@ -query getPost($slug: String, $language_code: String) { +query getPost($slug: String) { posts(filters: { slug: { eq: $slug } }) { data { id @@ -12,16 +12,14 @@ query getPost($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } diff --git a/src/graphql/operations/getVideo.graphql b/src/graphql/operations/getVideo.graphql index 06270a0..de5689e 100644 --- a/src/graphql/operations/getVideo.graphql +++ b/src/graphql/operations/getVideo.graphql @@ -23,9 +23,8 @@ query getVideo($uid: String) { } categories(pagination: { limit: -1 }) { data { - id attributes { - short + slug } } } diff --git a/src/graphql/operations/getWeapon.graphql b/src/graphql/operations/getWeapon.graphql index 20565fa..877fe55 100644 --- a/src/graphql/operations/getWeapon.graphql +++ b/src/graphql/operations/getWeapon.graphql @@ -1,4 +1,4 @@ -query getWeapon($slug: String, $language_code: String) { +query getWeapon($slug: String) { weaponStories(filters: { slug: { eq: $slug } }) { data { attributes { @@ -7,10 +7,8 @@ query getWeapon($slug: String, $language_code: String) { id categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -57,16 +55,6 @@ fragment sharedWeaponFragment on WeaponStory { id attributes { slug - translations(filters: { language: { code: { eq: $language_code } } }) { - name - language { - data { - attributes { - code - } - } - } - } } } } diff --git a/src/graphql/operations/getWikiPage.graphql b/src/graphql/operations/getWikiPage.graphql index 0507da1..5065189 100644 --- a/src/graphql/operations/getWikiPage.graphql +++ b/src/graphql/operations/getWikiPage.graphql @@ -1,4 +1,4 @@ -query getWikiPage($slug: String, $language_code: String) { +query getWikiPage($slug: String) { wikiPages(filters: { slug: { eq: $slug } }) { data { id @@ -13,21 +13,15 @@ query getWikiPage($slug: String, $language_code: String) { } categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } tags { data { - id attributes { slug - titles(filters: { language: { code: { eq: $language_code } } }) { - title - } } } } @@ -58,7 +52,7 @@ query getWikiPage($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -66,7 +60,7 @@ query getWikiPage($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -74,7 +68,7 @@ query getWikiPage($slug: String, $language_code: String) { data { id attributes { - ...recorderChip + username } } } @@ -90,10 +84,8 @@ query getWikiPage($slug: String, $language_code: String) { } categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } diff --git a/src/graphql/operations/local-data/localDataGetRecorders.graphql b/src/graphql/operations/local-data/localDataGetRecorders.graphql new file mode 100644 index 0000000..d58e45d --- /dev/null +++ b/src/graphql/operations/local-data/localDataGetRecorders.graphql @@ -0,0 +1,36 @@ +query localDataGetRecorders { + recorders(pagination: { limit: -1 }) { + data { + attributes { + username + anonymize + anonymous_code + pronouns + bio(pagination: { limit: -1 }) { + bio + language { + data { + attributes { + code + } + } + } + } + languages(pagination: { limit: -1 }) { + data { + attributes { + code + } + } + } + avatar { + data { + attributes { + ...uploadImage + } + } + } + } + } + } +} diff --git a/src/graphql/operations/local-data/localDataGetTypesTranslations.graphql b/src/graphql/operations/local-data/localDataGetTypesTranslations.graphql new file mode 100644 index 0000000..feb7a83 --- /dev/null +++ b/src/graphql/operations/local-data/localDataGetTypesTranslations.graphql @@ -0,0 +1,183 @@ +query localDataGetTypesTranslations { + metadataTypes(pagination: { limit: -1 }) { + data { + attributes { + slug + titles { + language { + data { + attributes { + code + } + } + } + title + } + } + } + } + + audioSubtypes(pagination: { limit: -1 }) { + data { + attributes { + slug + titles { + language { + data { + attributes { + code + } + } + } + title + } + } + } + } + + videoSubtypes(pagination: { limit: -1 }) { + data { + attributes { + slug + titles { + language { + data { + attributes { + code + } + } + } + title + } + } + } + } + + textualSubtypes(pagination: { limit: -1 }) { + data { + attributes { + slug + titles { + language { + data { + attributes { + code + } + } + } + title + } + } + } + } + + groupSubtypes(pagination: { limit: -1 }) { + data { + attributes { + slug + titles { + language { + data { + attributes { + code + } + } + } + title + } + } + } + } + + gamePlatforms(pagination: { limit: -1 }) { + data { + attributes { + slug + titles { + language { + data { + attributes { + code + } + } + } + title + short + } + } + } + } + + contentTypes(pagination: { limit: -1 }) { + data { + attributes { + slug + titles { + language { + data { + attributes { + code + } + } + } + title + } + } + } + } + + wikiPagesTags(pagination: { limit: -1 }) { + data { + attributes { + slug + titles { + language { + data { + attributes { + code + } + } + } + title + } + } + } + } + + weaponStoryTypes(pagination: { limit: -1 }) { + data { + attributes { + slug + translations { + language { + data { + attributes { + code + } + } + } + name + } + } + } + } + + categories(pagination: { limit: -1 }) { + data { + attributes { + slug + titles { + language { + data { + attributes { + code + } + } + } + title + short + } + } + } + } +} diff --git a/src/graphql/operations/local-data/localDataGetWebsiteInterfaces.graphql b/src/graphql/operations/local-data/localDataGetWebsiteInterfaces.graphql index f9ce9ea..225b297 100644 --- a/src/graphql/operations/local-data/localDataGetWebsiteInterfaces.graphql +++ b/src/graphql/operations/local-data/localDataGetWebsiteInterfaces.graphql @@ -114,11 +114,11 @@ query localDataGetWebsiteInterfaces { previous_content followup_content videos - view_on + view_on_x channel subscribers description - available_at + available_at_x want_it have_it source diff --git a/src/helpers/formatters.ts b/src/helpers/formatters.ts index 4366cdc..b437a7d 100644 --- a/src/helpers/formatters.ts +++ b/src/helpers/formatters.ts @@ -62,135 +62,6 @@ export const prettyInlineTitle = ( return result; }; -export const prettyItemSubType = ( - metadata: - | { - __typename: "ComponentMetadataAudio"; - subtype?: { - data?: { - attributes?: { - slug: string; - titles?: - | ({ - title: string; - } | null)[] - | null; - } | null; - } | null; - } | null; - } - | { - __typename: "ComponentMetadataBooks"; - subtype?: { - data?: { - attributes?: { - slug: string; - titles?: - | ({ - title: string; - } | null)[] - | null; - } | null; - } | null; - } | null; - } - | { - __typename: "ComponentMetadataGame"; - platforms?: { - data: { - id?: string | null; - attributes?: { - short: string; - } | null; - }[]; - } | null; - } - | { - __typename: "ComponentMetadataGroup"; - subtype?: { - data?: { - attributes?: { - slug: string; - titles?: - | ({ - title: string; - } | null)[] - | null; - } | null; - } | null; - } | null; - subitems_type?: { - data?: { - attributes?: { - slug: string; - titles?: - | ({ - title: string; - } | null)[] - | null; - } | null; - } | null; - } | null; - } - | { - __typename: "ComponentMetadataVideo"; - subtype?: { - data?: { - attributes?: { - slug: string; - titles?: - | ({ - title: string; - } | null)[] - | null; - } | null; - } | null; - } | null; - } - | { __typename: "ComponentMetadataOther" } - | { __typename: "Error" } - | null -): string => { - if (metadata) { - switch (metadata.__typename) { - case "ComponentMetadataAudio": - case "ComponentMetadataBooks": - case "ComponentMetadataVideo": - return metadata.subtype?.data?.attributes?.titles && - metadata.subtype.data.attributes.titles.length > 0 && - metadata.subtype.data.attributes.titles[0] - ? metadata.subtype.data.attributes.titles[0].title - : prettySlug(metadata.subtype?.data?.attributes?.slug); - case "ComponentMetadataGame": - return metadata.platforms?.data && - metadata.platforms.data.length > 0 && - metadata.platforms.data[0]?.attributes - ? metadata.platforms.data[0].attributes.short - : ""; - case "ComponentMetadataGroup": { - const firstPart = - metadata.subtype?.data?.attributes?.titles && - metadata.subtype.data.attributes.titles.length > 0 && - metadata.subtype.data.attributes.titles[0] - ? metadata.subtype.data.attributes.titles[0].title - : prettySlug(metadata.subtype?.data?.attributes?.slug); - - const secondPart = - metadata.subitems_type?.data?.attributes?.titles && - metadata.subitems_type.data.attributes.titles.length > 0 && - metadata.subitems_type.data.attributes.titles[0] - ? metadata.subitems_type.data.attributes.titles[0].title - : prettySlug(metadata.subitems_type?.data?.attributes?.slug); - return `${secondPart} ${firstPart}`; - } - default: - return ""; - } - } - return ""; -}; -/* eslint-enable id-denylist */ - export const prettyShortenNumber = (number: number): string => { if (number > 1_000_000) { return `${(number / 1_000_000).toLocaleString(undefined, { diff --git a/src/helpers/i18n.ts b/src/helpers/i18n.ts index f6d571b..51c35c7 100644 --- a/src/helpers/i18n.ts +++ b/src/helpers/i18n.ts @@ -2,7 +2,9 @@ import { IntlMessageFormat } from "intl-messageformat"; import { LibraryItemMetadataDynamicZone } from "graphql/generated"; import { ICUParams } from "graphql/icuParams"; import { isDefined, isDefinedAndNotEmpty } from "helpers/asserts"; -import { getLangui } from "graphql/fetchLocalData"; +import { getLangui, getTypesTranslations } from "graphql/fetchLocalData"; +import { prettySlug } from "helpers/formatters"; +import { LibraryItemMetadata } from "types/types"; type WordingKey = keyof ICUParams; type LibraryItemType = Exclude; @@ -29,18 +31,24 @@ const componentSetsTextsetStatusToWording: Record< }; export const getFormat = ( - locale: string | undefined + locale: string | undefined = "en" ): { format: ( key: K, ...values: ICUParams[K] extends never ? [undefined?] : [ICUParams[K]] ) => string; - formatLibraryItemType: (metadata: { __typename: LibraryItemType }) => string; + formatLibraryItemType: (metadata: LibraryItemMetadata) => string; + formatLibraryItemSubType: (metadata: LibraryItemMetadata) => string; formatStatusLabel: (status: ContentStatus) => string; formatStatusDescription: (status: ContentStatus) => string; + formatCategory: (slug: string, type?: "default" | "full") => string; + formatContentType: (slug: string) => string; + formatWikiTag: (slug: string) => string; + formatWeaponType: (slug: string) => string; } => { const langui = getLangui(locale); const fallbackLangui = getLangui("en"); + const typesTranslations = getTypesTranslations(); const format = ( key: WordingKey, @@ -65,8 +73,90 @@ export const getFormat = ( return key; }; - const formatLibraryItemType = (metadata: { __typename: LibraryItemType }): string => - format(componentMetadataToWording[metadata.__typename]); + const formatLibraryItemType = (metadata: LibraryItemMetadata): string => + metadata ? format(componentMetadataToWording[metadata.__typename]) : format("other"); + + const formatLibraryItemSubType = (metadata: LibraryItemMetadata): string => { + switch (metadata?.__typename) { + case "ComponentMetadataAudio": { + const slug = metadata.subtype?.data?.attributes?.slug; + const subtype = typesTranslations.audioSubtypes.find( + (type) => type.attributes?.slug === slug + ); + const findTranslation = (givenLocale: string) => + subtype?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + } + + case "ComponentMetadataBooks": { + const slug = metadata.subtype?.data?.attributes?.slug; + const subtype = typesTranslations.textualSubtypes.find( + (type) => type.attributes?.slug === slug + ); + const findTranslation = (givenLocale: string) => + subtype?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + } + + case "ComponentMetadataVideo": { + const slug = metadata.subtype?.data?.attributes?.slug; + const subtype = typesTranslations.videoSubtypes.find( + (type) => type.attributes?.slug === slug + ); + const findTranslation = (givenLocale: string) => + subtype?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + } + + case "ComponentMetadataGame": { + const slug = metadata.platform?.data?.attributes?.slug; + const subtype = typesTranslations.gamePlatforms.find( + (type) => type.attributes?.slug === slug + ); + console.log(slug); + const findTranslation = (givenLocale: string) => + subtype?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + } + + case "ComponentMetadataGroup": { + const subItemType = (() => { + const subitemTypeSlug = metadata.subitems_type?.data?.attributes?.slug; + const subItemTypeTranslations = typesTranslations.metadataTypes.find( + (type) => type.attributes?.slug === subitemTypeSlug + ); + const findTranslation = (givenLocale: string) => + subItemTypeTranslations?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + })(); + const groupType = (() => { + const groupTypeSlug = metadata.subtype?.data?.attributes?.slug; + const groupTypeTranslations = typesTranslations.groupSubtypes.find( + (type) => type.attributes?.slug === groupTypeSlug + ); + const findTranslation = (givenLocale: string) => + groupTypeTranslations?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + })(); + return `${groupType} - ${subItemType}`; + } + + default: + return format("other"); + } + }; const formatStatusLabel = (status: ContentStatus): string => format(componentSetsTextsetStatusToWording[status].label); @@ -74,10 +164,65 @@ export const getFormat = ( const formatStatusDescription = (status: ContentStatus): string => format(componentSetsTextsetStatusToWording[status].description); + const formatCategory = (slug: string, type: "default" | "full" = "default"): string => { + const category = typesTranslations.categories.find((cat) => cat.attributes?.slug === slug); + if (!category) return prettySlug(slug); + const findTranslation = (givenLocale: string): string | null | undefined => { + const localeTranslation = category.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + ); + return type === "default" ? localeTranslation?.title : localeTranslation?.short; + }; + return findTranslation(locale) ?? findTranslation("en") ?? prettySlug(slug); + }; + + const formatContentType = (slug: string): string => { + const contentType = typesTranslations.contentTypes.find( + (type) => type.attributes?.slug === slug + ); + if (!contentType) return prettySlug(slug); + const findTranslation = (givenLocale: string): string | null | undefined => { + const localeTranslation = contentType.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + ); + return localeTranslation?.title; + }; + return findTranslation(locale) ?? findTranslation("en") ?? prettySlug(slug); + }; + + const formatWikiTag = (slug: string): string => { + const wikiTag = typesTranslations.wikiPagesTags.find((cat) => cat.attributes?.slug === slug); + if (!wikiTag) return prettySlug(slug); + const findTranslation = (givenLocale: string): string | null | undefined => { + const localeTranslation = wikiTag.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + ); + return localeTranslation?.title; + }; + return findTranslation(locale) ?? findTranslation("en") ?? prettySlug(slug); + }; + + const formatWeaponType = (slug: string): string => { + const weaponType = typesTranslations.weaponTypes.find((type) => type.attributes?.slug === slug); + if (!weaponType) return prettySlug(slug); + const findTranslation = (givenLocale: string): string | null | undefined => { + const localeTranslation = weaponType.attributes?.translations?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + ); + return localeTranslation?.name; + }; + return findTranslation(locale) ?? findTranslation("en") ?? prettySlug(slug); + }; + return { format, formatLibraryItemType, + formatLibraryItemSubType, formatStatusLabel, formatStatusDescription, + formatCategory, + formatContentType, + formatWikiTag, + formatWeaponType, }; }; diff --git a/src/helpers/localData.ts b/src/helpers/localData.ts index 48d4fc0..468c3f1 100644 --- a/src/helpers/localData.ts +++ b/src/helpers/localData.ts @@ -1,6 +1,8 @@ import { LocalDataGetCurrenciesQuery, LocalDataGetLanguagesQuery, + LocalDataGetRecordersQuery, + LocalDataGetTypesTranslationsQuery, LocalDataGetWebsiteInterfacesQuery, } from "graphql/generated"; @@ -45,3 +47,58 @@ export const processLanguages = (languages: LocalDataGetLanguagesQuery | undefin } return languages?.languages?.data ?? []; }; + +// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + +export type Recorders = NonNullable["data"]; + +export const processRecorders = (recorders: LocalDataGetRecordersQuery | undefined): Recorders => + recorders?.recorders?.data ?? []; + +// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + +export type TypesTranslations = { + audioSubtypes: NonNullable< + NonNullable["audioSubtypes"] + >["data"]; + gamePlatforms: NonNullable< + NonNullable["gamePlatforms"] + >["data"]; + groupSubtypes: NonNullable< + NonNullable["groupSubtypes"] + >["data"]; + metadataTypes: NonNullable< + NonNullable["metadataTypes"] + >["data"]; + textualSubtypes: NonNullable< + NonNullable["textualSubtypes"] + >["data"]; + videoSubtypes: NonNullable< + NonNullable["videoSubtypes"] + >["data"]; + contentTypes: NonNullable< + NonNullable["contentTypes"] + >["data"]; + wikiPagesTags: NonNullable< + NonNullable["wikiPagesTags"] + >["data"]; + weaponTypes: NonNullable< + NonNullable["weaponStoryTypes"] + >["data"]; + categories: NonNullable["categories"]>["data"]; +}; + +export const processTypesTranslations = ( + data: LocalDataGetTypesTranslationsQuery | undefined +): TypesTranslations => ({ + audioSubtypes: data?.audioSubtypes?.data ?? [], + categories: data?.categories?.data ?? [], + contentTypes: data?.contentTypes?.data ?? [], + gamePlatforms: data?.gamePlatforms?.data ?? [], + groupSubtypes: data?.groupSubtypes?.data ?? [], + metadataTypes: data?.metadataTypes?.data ?? [], + textualSubtypes: data?.textualSubtypes?.data ?? [], + videoSubtypes: data?.videoSubtypes?.data ?? [], + weaponTypes: data?.weaponStoryTypes?.data ?? [], + wikiPagesTags: data?.wikiPagesTags?.data ?? [], +}); diff --git a/src/hooks/useFormat.ts b/src/hooks/useFormat.ts index 90a9be5..65c4ed2 100644 --- a/src/hooks/useFormat.ts +++ b/src/hooks/useFormat.ts @@ -1,11 +1,14 @@ import { IntlMessageFormat } from "intl-messageformat"; import { useCallback } from "react"; +import { useRouter } from "next/router"; import { atoms } from "contexts/atoms"; import { useAtomGetter } from "helpers/atoms"; import { LibraryItemMetadataDynamicZone } from "graphql/generated"; import { ICUParams } from "graphql/icuParams"; import { isDefined, isDefinedAndNotEmpty } from "helpers/asserts"; import { getLogger } from "helpers/logger"; +import { prettySlug } from "helpers/formatters"; +import { LibraryItemMetadata } from "types/types"; const logger = getLogger("🗺️ [I18n]"); @@ -58,12 +61,19 @@ export const useFormat = (): { key: K, ...values: ICUParams[K] extends never ? [undefined?] : [ICUParams[K]] ) => string; - formatLibraryItemType: (metadata: { __typename: LibraryItemType }) => string; + formatLibraryItemType: (metadata: LibraryItemMetadata) => string; + formatLibraryItemSubType: (metadata: LibraryItemMetadata) => string; formatStatusLabel: (status: ContentStatus) => string; formatStatusDescription: (status: ContentStatus) => string; + formatCategory: (slug: string, type?: "default" | "full") => string; + formatContentType: (slug: string) => string; + formatWikiTag: (slug: string) => string; + formatWeaponType: (slug: string) => string; } => { const langui = useAtomGetter(atoms.localData.langui); const fallbackLangui = useAtomGetter(atoms.localData.fallbackLangui); + const typesTranslations = useAtomGetter(atoms.localData.typesTranslations); + const { locale = "en" } = useRouter(); const format = useCallback( ( @@ -96,12 +106,6 @@ Falling back to en translation.` [langui, fallbackLangui] ); - const formatLibraryItemType = useCallback( - (metadata: { __typename: LibraryItemType }): string => - format(componentMetadataToWording[metadata.__typename]), - [format] - ); - const formatStatusLabel = useCallback( (status: ContentStatus): string => format(componentSetsTextsetStatusToWording[status].label), [format] @@ -113,10 +117,178 @@ Falling back to en translation.` [format] ); + const formatLibraryItemType = useCallback( + (metadata: LibraryItemMetadata): string => + metadata ? format(componentMetadataToWording[metadata.__typename]) : format("other"), + [format] + ); + + const formatLibraryItemSubType = useCallback( + (metadata: LibraryItemMetadata): string => { + switch (metadata?.__typename) { + case "ComponentMetadataAudio": { + const slug = metadata.subtype?.data?.attributes?.slug; + const subtype = typesTranslations.audioSubtypes.find( + (type) => type.attributes?.slug === slug + ); + const findTranslation = (givenLocale: string) => + subtype?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + } + + case "ComponentMetadataBooks": { + const slug = metadata.subtype?.data?.attributes?.slug; + const subtype = typesTranslations.textualSubtypes.find( + (type) => type.attributes?.slug === slug + ); + const findTranslation = (givenLocale: string) => + subtype?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + } + + case "ComponentMetadataVideo": { + const slug = metadata.subtype?.data?.attributes?.slug; + const subtype = typesTranslations.videoSubtypes.find( + (type) => type.attributes?.slug === slug + ); + const findTranslation = (givenLocale: string) => + subtype?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + } + + case "ComponentMetadataGame": { + const slug = metadata.platform?.data?.attributes?.slug; + const subtype = typesTranslations.gamePlatforms.find( + (type) => type.attributes?.slug === slug + ); + const findTranslation = (givenLocale: string) => + subtype?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + } + + case "ComponentMetadataGroup": { + const subItemType = (() => { + const subitemTypeSlug = metadata.subitems_type?.data?.attributes?.slug; + const subItemTypeTranslations = typesTranslations.metadataTypes.find( + (type) => type.attributes?.slug === subitemTypeSlug + ); + const findTranslation = (givenLocale: string) => + subItemTypeTranslations?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + })(); + const groupType = (() => { + const groupTypeSlug = metadata.subtype?.data?.attributes?.slug; + const groupTypeTranslations = typesTranslations.groupSubtypes.find( + (type) => type.attributes?.slug === groupTypeSlug + ); + const findTranslation = (givenLocale: string) => + groupTypeTranslations?.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + )?.title; + return findTranslation(locale) ?? findTranslation("en") ?? format("other"); + })(); + return `${groupType} - ${subItemType}`; + } + + default: + return format("other"); + } + }, + [ + format, + locale, + typesTranslations.audioSubtypes, + typesTranslations.gamePlatforms, + typesTranslations.groupSubtypes, + typesTranslations.metadataTypes, + typesTranslations.textualSubtypes, + typesTranslations.videoSubtypes, + ] + ); + + const formatCategory = useCallback( + (slug: string, type: "default" | "full" = "default"): string => { + const category = typesTranslations.categories.find((cat) => cat.attributes?.slug === slug); + if (!category) return prettySlug(slug); + const findTranslation = (givenLocale: string): string | null | undefined => { + const localeTranslation = category.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + ); + return type === "full" ? localeTranslation?.title : localeTranslation?.short; + }; + return findTranslation(locale) ?? findTranslation("en") ?? prettySlug(slug); + }, + [locale, typesTranslations.categories] + ); + + const formatContentType = useCallback( + (slug: string): string => { + const contentType = typesTranslations.contentTypes.find( + (type) => type.attributes?.slug === slug + ); + if (!contentType) return prettySlug(slug); + const findTranslation = (givenLocale: string): string | null | undefined => { + const localeTranslation = contentType.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + ); + return localeTranslation?.title; + }; + return findTranslation(locale) ?? findTranslation("en") ?? prettySlug(slug); + }, + [locale, typesTranslations.contentTypes] + ); + + const formatWikiTag = useCallback( + (slug: string): string => { + const wikiTag = typesTranslations.wikiPagesTags.find((cat) => cat.attributes?.slug === slug); + if (!wikiTag) return prettySlug(slug); + const findTranslation = (givenLocale: string): string | null | undefined => { + const localeTranslation = wikiTag.attributes?.titles?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + ); + return localeTranslation?.title; + }; + return findTranslation(locale) ?? findTranslation("en") ?? prettySlug(slug); + }, + [locale, typesTranslations.wikiPagesTags] + ); + + const formatWeaponType = useCallback( + (slug: string): string => { + const weaponType = typesTranslations.weaponTypes.find( + (type) => type.attributes?.slug === slug + ); + if (!weaponType) return prettySlug(slug); + const findTranslation = (givenLocale: string): string | null | undefined => { + const localeTranslation = weaponType.attributes?.translations?.find( + (translation) => translation?.language?.data?.attributes?.code === givenLocale + ); + return localeTranslation?.name; + }; + return findTranslation(locale) ?? findTranslation("en") ?? prettySlug(slug); + }, + [locale, typesTranslations.weaponTypes] + ); + return { format, formatLibraryItemType, + formatLibraryItemSubType, formatStatusLabel, formatStatusDescription, + formatCategory, + formatContentType, + formatWikiTag, + formatWeaponType, }; }; diff --git a/src/pages/api/revalidate.ts b/src/pages/api/revalidate.ts index 71df0bb..d2e8d12 100644 --- a/src/pages/api/revalidate.ts +++ b/src/pages/api/revalidate.ts @@ -2,7 +2,13 @@ import type { NextApiRequest, NextApiResponse } from "next"; import { i18n } from "../../../next.config"; import { cartesianProduct } from "helpers/others"; import { filterHasAttributes } from "helpers/asserts"; -import { fetchLocalData } from "graphql/fetchLocalData"; +import { + fetchCurrencies, + fetchLanguages, + fetchRecorders, + fetchTypesTranslations, + fetchWebsiteInterfaces, +} from "graphql/fetchLocalData"; import { getReadySdk } from "graphql/sdk"; type CRUDEvents = "entry.create" | "entry.delete" | "entry.update"; @@ -20,21 +26,32 @@ type StrapiRelationalFieldEntry = { type RequestProps = | CustomRequest + | StrapiAudioSubType + | StrapiCategory | StrapiChronicle | StrapiChronicleChapter | StrapiChronology | StrapiContent | StrapiContentFolder + | StrapiContentType | StrapiCurrency + | StrapiGamePlatform + | StrapiGroupSubtypes | StrapiLanguage | StrapiLibraryItem + | StrapiMetadataType | StrapiPostContent | StrapiRangedContent + | StrapiRecorder + | StrapiTextualSubtypes | StrapiVideo + | StrapiVideoSubType | StrapiWeaponGroup | StrapiWeaponStory + | StrapiWeaponStoryType | StrapiWebsiteInterface - | StrapiWiki; + | StrapiWiki + | StrapiWikiPagesTag; interface CustomRequest { model: "custom"; @@ -57,7 +74,6 @@ interface StrapiWeaponGroup extends StrapiEvent { } interface StrapiRangedContent extends StrapiEvent { - event: CRUDEvents; model: "ranged-content"; entry: { id: string; @@ -78,7 +94,6 @@ interface StrapiContent extends StrapiEvent { } interface StrapiPostContent extends StrapiEvent { - event: CRUDEvents; model: "post"; entry: { slug: string; @@ -86,31 +101,62 @@ interface StrapiPostContent extends StrapiEvent { } interface StrapiWebsiteInterface extends StrapiEvent { - event: CRUDEvents; model: "website-interface"; - entry: { - slug: string; - }; +} + +interface StrapiRecorder extends StrapiEvent { + model: "recorder"; +} + +interface StrapiMetadataType extends StrapiEvent { + model: "metadata-type"; +} + +interface StrapiAudioSubType extends StrapiEvent { + model: "audio-subtype"; +} + +interface StrapiVideoSubType extends StrapiEvent { + model: "video-subtype"; +} + +interface StrapiTextualSubtypes extends StrapiEvent { + model: "textual-subtype"; +} + +interface StrapiGroupSubtypes extends StrapiEvent { + model: "group-subtype"; +} + +interface StrapiGamePlatform extends StrapiEvent { + model: "game-platform"; +} + +interface StrapiContentType extends StrapiEvent { + model: "content-type"; +} + +interface StrapiWikiPagesTag extends StrapiEvent { + model: "wiki-pages-tag"; +} + +interface StrapiWeaponStoryType extends StrapiEvent { + model: "weapon-story-type"; +} + +interface StrapiCategory extends StrapiEvent { + model: "category"; } interface StrapiLanguage extends StrapiEvent { - event: CRUDEvents; model: "language"; - entry: { - slug: string; - }; } interface StrapiCurrency extends StrapiEvent { - event: CRUDEvents; model: "currency"; - entry: { - slug: string; - }; } interface StrapiLibraryItem extends StrapiEvent { - event: CRUDEvents; model: "library-item"; entry: { slug: string; @@ -121,7 +167,6 @@ interface StrapiLibraryItem extends StrapiEvent { } interface StrapiContentFolder extends StrapiEvent { - event: CRUDEvents; model: "contents-folder"; entry: { slug: string; @@ -132,12 +177,10 @@ interface StrapiContentFolder extends StrapiEvent { } interface StrapiChronology extends StrapiEvent { - event: CRUDEvents; model: "chronology-era" | "chronology-item"; } interface StrapiWiki extends StrapiEvent { - event: CRUDEvents; model: "wiki-page"; entry: { slug: string; @@ -145,7 +188,6 @@ interface StrapiWiki extends StrapiEvent { } interface StrapiChronicle extends StrapiEvent { - event: CRUDEvents; model: "chronicle"; entry: { slug: string; @@ -153,7 +195,6 @@ interface StrapiChronicle extends StrapiEvent { } interface StrapiChronicleChapter extends StrapiEvent { - event: CRUDEvents; model: "chronicles-chapter"; entry: { chronicles: StrapiRelationalFieldEntry[]; @@ -161,7 +202,6 @@ interface StrapiChronicleChapter extends StrapiEvent { } interface StrapiVideo extends StrapiEvent { - event: CRUDEvents; model: "video"; entry: { uid: string; @@ -322,13 +362,6 @@ const Revalidate = async ( break; } - case "website-interface": - case "language": - case "currency": { - await fetchLocalData(); - break; - } - case "video": { if (body.entry.uid) { paths.push(`/archives/videos/v/${body.entry.uid}`); @@ -351,6 +384,38 @@ const Revalidate = async ( break; } + case "recorder": { + await fetchRecorders(); + break; + } + + case "audio-subtype": + case "textual-subtype": + case "video-subtype": + case "group-subtype": + case "game-platform": + case "metadata-type": + case "content-type": + case "weapon-story-type": + case "category": + case "wiki-pages-tag": { + await fetchTypesTranslations(); + break; + } + + case "website-interface": { + await fetchWebsiteInterfaces(); + break; + } + case "language": { + await fetchLanguages(); + break; + } + case "currency": { + await fetchCurrencies(); + break; + } + case "custom": { paths.push(`${body.path}`); break; diff --git a/src/pages/chronicles/[slug]/index.tsx b/src/pages/chronicles/[slug]/index.tsx index 7199633..48e9c14 100644 --- a/src/pages/chronicles/[slug]/index.tsx +++ b/src/pages/chronicles/[slug]/index.tsx @@ -34,7 +34,7 @@ interface Props extends AppLayoutRequired { } const Chronicle = ({ chronicle, chapters, ...otherProps }: Props): JSX.Element => { - const { format } = useFormat(); + const { format, formatContentType, formatCategory } = useFormat(); useScrollTopOnChange(Ids.ContentPanel, [chronicle.slug]); const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = useSmartLanguage({ @@ -111,8 +111,14 @@ const Chronicle = ({ chronicle, chapters, ...otherProps }: Props): JSX.Element = ) : undefined } - categories={primaryContent?.categories} - type={primaryContent?.type} + categories={filterHasAttributes(primaryContent?.categories?.data, [ + "attributes", + ]).map((category) => formatCategory(category.attributes.slug))} + type={ + primaryContent?.type?.data?.attributes + ? formatContentType(primaryContent.type.data.attributes.slug) + : undefined + } description={selectedContentTranslation.description} thumbnail={primaryContent?.thumbnail?.data?.attributes} />, @@ -146,13 +152,10 @@ export default Chronicle; export const getStaticProps: GetStaticProps = async (context) => { const sdk = getReadySdk(); - const { format } = getFormat(context.locale); + const { format, formatCategory, formatContentType } = getFormat(context.locale); const slug = context.params && isDefined(context.params.slug) ? context.params.slug.toString() : ""; - const chronicle = await sdk.getChronicle({ - language_code: context.locale ?? "en", - slug: slug, - }); + const chronicle = await sdk.getChronicle({ slug: slug }); const chronicles = await sdk.getChroniclesChapters(); if ( !chronicle.chronicles?.data[0]?.attributes?.translations || @@ -178,13 +181,18 @@ export const getStaticProps: GetStaticProps = async (context) => { description: getDescription(selectedContentTranslation.description, { [format("type", { count: Infinity })]: [ chronicle.chronicles.data[0].attributes.contents.data[0].attributes.type?.data - ?.attributes?.titles?.[0]?.title, + ?.attributes + ? formatContentType( + chronicle.chronicles.data[0].attributes.contents.data[0].attributes.type.data + .attributes.slug + ) + : undefined, ], [format("category", { count: Infinity })]: filterHasAttributes( chronicle.chronicles.data[0].attributes.contents.data[0].attributes.categories ?.data, ["attributes"] - ).map((category) => category.attributes.short), + ).map((category) => formatCategory(category.attributes.slug)), }), }; } diff --git a/src/pages/contents/[slug].tsx b/src/pages/contents/[slug].tsx index 0823256..15057df 100644 --- a/src/pages/contents/[slug].tsx +++ b/src/pages/contents/[slug].tsx @@ -10,7 +10,7 @@ import { SubPanel } from "components/Containers/SubPanel"; import { PreviewCard, TranslatedPreviewCard } from "components/PreviewCard"; import { ThumbnailHeader } from "components/ThumbnailHeader"; import { getReadySdk } from "graphql/sdk"; -import { prettyInlineTitle, prettyItemSubType, prettySlug } from "helpers/formatters"; +import { prettyInlineTitle, prettySlug } from "helpers/formatters"; import { isUntangibleGroupItem } from "helpers/libraryItem"; import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts"; import { ContentWithTranslations } from "types/types"; @@ -47,7 +47,7 @@ interface Props extends AppLayoutRequired { const Content = ({ content, ...otherProps }: Props): JSX.Element => { const setSubPanelOpened = useAtomSetter(atoms.layout.subPanelOpened); const is1ColumnLayout = useAtomGetter(atoms.containerQueries.is1ColumnLayout); - const { format } = useFormat(); + const { format, formatCategory, formatLibraryItemSubType, formatContentType } = useFormat(); const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = useSmartLanguage({ items: content.translations, @@ -196,12 +196,12 @@ const Content = ({ content, ...otherProps }: Props): JSX.Element => { libraryItem.attributes.metadata && libraryItem.attributes.metadata.length > 0 && libraryItem.attributes.metadata[0] - ? [prettyItemSubType(libraryItem.attributes.metadata[0])] + ? [formatLibraryItemSubType(libraryItem.attributes.metadata[0])] : [] } bottomChips={filterHasAttributes(libraryItem.attributes.categories?.data, [ "attributes", - ]).map((category) => category.attributes.short)} + ]).map((category) => formatCategory(category.attributes.slug))} metadata={{ releaseDate: libraryItem.attributes.release_date, price: libraryItem.attributes.price, @@ -250,8 +250,14 @@ const Content = ({ content, ...otherProps }: Props): JSX.Element => { title={selectedTranslation?.title} subtitle={selectedTranslation?.subtitle} description={selectedTranslation?.description} - type={content.type} - categories={content.categories} + categories={filterHasAttributes(content.categories?.data, ["attributes"]).map( + (category) => formatCategory(category.attributes.slug) + )} + type={ + content.type?.data?.attributes + ? formatContentType(content.type.data.attributes.slug) + : undefined + } languageSwitcher={ languageSwitcherProps.locales.size > 1 ? ( @@ -330,12 +336,9 @@ export default Content; export const getStaticProps: GetStaticProps = async (context) => { const sdk = getReadySdk(); - const { format } = getFormat(context.locale); + const { format, formatCategory, formatContentType } = getFormat(context.locale); const slug = context.params?.slug ? context.params.slug.toString() : ""; - const content = await sdk.getContentText({ - slug: slug, - language_code: context.locale ?? "en", - }); + const content = await sdk.getContentText({ slug: slug }); if (!content.contents?.data[0]?.attributes?.translations) { return { notFound: true }; @@ -361,12 +364,14 @@ export const getStaticProps: GetStaticProps = async (context) => { ), description: getDescription(rawDescription, { [format("type", { count: Infinity })]: [ - content.contents.data[0].attributes.type?.data?.attributes?.titles?.[0]?.title, + content.contents.data[0].attributes.type?.data?.attributes + ? formatContentType(content.contents.data[0].attributes.type.data.attributes.slug) + : undefined, ], [format("category", { count: Infinity })]: filterHasAttributes( content.contents.data[0].attributes.categories?.data, ["attributes"] - ).map((category) => category.attributes.short), + ).map((category) => formatCategory(category.attributes.slug)), }), audio: selectedTranslation.language?.data?.attributes?.code && selectedTranslation.audio_set @@ -470,6 +475,7 @@ const RelatedContentPreview = ({ categories, type, }: RelatedContentPreviewFragment) => { + const { formatCategory, formatContentType } = useFormat(); const isContentPanelAtLeastXl = useAtomGetter(atoms.containerQueries.isContentPanelAtLeastXl); return ( @@ -486,16 +492,10 @@ const RelatedContentPreview = ({ )} fallback={{ title: slug }} thumbnail={thumbnail?.data?.attributes} - topChips={ - type?.data?.attributes - ? [ - type.data.attributes.titles?.[0] - ? type.data.attributes.titles[0]?.title - : prettySlug(type.data.attributes.slug), - ] - : undefined - } - bottomChips={categories?.data.map((category) => category.attributes?.short ?? "")} + topChips={type?.data?.attributes ? [formatContentType(type.data.attributes.slug)] : undefined} + bottomChips={filterHasAttributes(categories?.data, ["attributes"]).map((category) => + formatCategory(category.attributes.slug) + )} keepInfoVisible /> ); diff --git a/src/pages/contents/all.tsx b/src/pages/contents/all.tsx index fa3bf4e..f3eeee6 100644 --- a/src/pages/contents/all.tsx +++ b/src/pages/contents/all.tsx @@ -59,7 +59,7 @@ interface Props extends AppLayoutRequired {} const Contents = (props: Props): JSX.Element => { const hoverable = useDeviceSupportsHover(); - const { format } = useFormat(); + const { format, formatCategory, formatContentType } = useFormat(); const router = useTypedRouter(queryParamSchema); const setSubPanelOpened = useAtomSetter(atoms.layout.subPanelOpened); @@ -225,15 +225,11 @@ const Contents = (props: Props): JSX.Element => { thumbnailForceAspectRatio topChips={ item.type?.data?.attributes - ? [ - item.type.data.attributes.titles?.[0] - ? item.type.data.attributes.titles[0]?.title - : prettySlug(item.type.data.attributes.slug), - ] + ? [formatContentType(item.type.data.attributes.slug)] : undefined } - bottomChips={item.categories?.data.map( - (category) => category.attributes?.short ?? "" + bottomChips={filterHasAttributes(item.categories?.data, ["attributes"]).map( + (category) => formatCategory(category.attributes.slug) )} keepInfoVisible={keepInfoVisible} /> diff --git a/src/pages/contents/folder/[slug].tsx b/src/pages/contents/folder/[slug].tsx index b63163f..f415e90 100644 --- a/src/pages/contents/folder/[slug].tsx +++ b/src/pages/contents/folder/[slug].tsx @@ -35,7 +35,7 @@ interface Props extends AppLayoutRequired { } const ContentsFolder = ({ openGraph, folder, path, ...otherProps }: Props): JSX.Element => { - const { format } = useFormat(); + const { format, formatCategory, formatContentType } = useFormat(); const setSubPanelOpened = useAtomSetter(atoms.layout.subPanelOpened); const isContentPanelAtLeast4xl = useAtomGetter(atoms.containerQueries.isContentPanelAtLeast4xl); @@ -158,16 +158,12 @@ const ContentsFolder = ({ openGraph, folder, path, ...otherProps }: Props): JSX. thumbnailForceAspectRatio topChips={ item.attributes.type?.data?.attributes - ? [ - item.attributes.type.data.attributes.titles?.[0] - ? item.attributes.type.data.attributes.titles[0]?.title - : prettySlug(item.attributes.type.data.attributes.slug), - ] + ? [formatContentType(item.attributes.type.data.attributes.slug)] : undefined } - bottomChips={item.attributes.categories?.data.map( - (category) => category.attributes?.short ?? "" - )} + bottomChips={filterHasAttributes(item.attributes.categories?.data, [ + "attributes", + ]).map((category) => formatCategory(category.attributes.slug))} keepInfoVisible /> ))} @@ -201,10 +197,7 @@ export const getStaticProps: GetStaticProps = async (context) => { const sdk = getReadySdk(); const { format } = getFormat(context.locale); const slug = context.params?.slug ? context.params.slug.toString() : ""; - const contentsFolder = await sdk.getContentsFolder({ - slug: slug, - language_code: context.locale ?? "en", - }); + const contentsFolder = await sdk.getContentsFolder({ slug: slug }); if (!contentsFolder.contentsFolders?.data[0]?.attributes) { return { notFound: true }; } diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 9189b5c..c18cebb 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -64,10 +64,7 @@ export default Home; export const getStaticProps: GetStaticProps = async (context) => { const sdk = getReadySdk(); const { format } = getFormat(context.locale); - const post = await sdk.getPost({ - slug: "home", - language_code: context.locale ?? "en", - }); + const post = await sdk.getPost({ slug: "home" }); if (post.posts?.data && post.posts.data.length > 0) { const props: PostStaticProps = { post: post.posts.data[0]?.attributes as PostWithTranslations, diff --git a/src/pages/library/[slug]/index.tsx b/src/pages/library/[slug]/index.tsx index 978f8be..2c16ee2 100644 --- a/src/pages/library/[slug]/index.tsx +++ b/src/pages/library/[slug]/index.tsx @@ -23,7 +23,6 @@ import { getReadySdk } from "graphql/sdk"; import { prettyDate, prettyInlineTitle, - prettyItemSubType, prettyPrice, prettySlug, prettyURL, @@ -91,7 +90,13 @@ const LibrarySlug = ({ }: Props): JSX.Element => { const currency = useAtomGetter(atoms.settings.currency); const isPerfModeEnabled = useAtomGetter(atoms.settings.isPerfModeEnabled); - const { format, formatLibraryItemType } = useFormat(); + const { + format, + formatLibraryItemType, + formatCategory, + formatContentType, + formatLibraryItemSubType, + } = useFormat(); const currencies = useAtomGetter(atoms.localData.currencies); const isContentPanelAtLeast3xl = useAtomGetter(atoms.containerQueries.isContentPanelAtLeast3xl); @@ -307,7 +312,7 @@ const LibrarySlug = ({
{"›"} - +
)} @@ -347,7 +352,10 @@ const LibrarySlug = ({
{filterHasAttributes(item.categories.data, ["attributes"]).map((category) => ( - + ))}
@@ -506,12 +514,12 @@ const LibrarySlug = ({ subitem.attributes.metadata && subitem.attributes.metadata.length > 0 && subitem.attributes.metadata[0] - ? [prettyItemSubType(subitem.attributes.metadata[0])] + ? [formatLibraryItemSubType(subitem.attributes.metadata[0])] : [] } - bottomChips={subitem.attributes.categories?.data.map( - (category) => category.attributes?.short ?? "" - )} + bottomChips={filterHasAttributes(subitem.attributes.categories?.data, [ + "attributes", + ]).map((category) => formatCategory(category.attributes.slug))} metadata={{ releaseDate: subitem.attributes.release_date, price: subitem.attributes.price, @@ -573,14 +581,14 @@ const LibrarySlug = ({ categories: filterHasAttributes( rangedContent.attributes.content.data.attributes.categories?.data, ["attributes"] - ).map((category) => category.attributes.short), - type: - rangedContent.attributes.content.data.attributes.type?.data - ?.attributes?.titles?.[0]?.title ?? - prettySlug( - rangedContent.attributes.content.data.attributes.type?.data - ?.attributes?.slug - ), + ).map((category) => formatCategory(category.attributes.slug)), + type: rangedContent.attributes.content.data.attributes.type?.data + ?.attributes + ? formatContentType( + rangedContent.attributes.content.data.attributes.type.data + .attributes.slug + ) + : undefined, slug: rangedContent.attributes.content.data.attributes.slug, } : undefined @@ -619,10 +627,9 @@ export default LibrarySlug; export const getStaticProps: GetStaticProps = async (context) => { const sdk = getReadySdk(); - const { format } = getFormat(context.locale); + const { format, formatCategory, formatLibraryItemSubType } = getFormat(context.locale); const item = await sdk.getLibraryItem({ slug: context.params && isDefined(context.params.slug) ? context.params.slug.toString() : "", - language_code: context.locale ?? "en", }); if (!item.libraryItems?.data[0]?.attributes) return { notFound: true }; sortRangedContent(item.libraryItems.data[0].attributes.contents); @@ -634,10 +641,10 @@ export const getStaticProps: GetStaticProps = async (context) => { { [format("category", { count: Infinity })]: filterHasAttributes( item.libraryItems.data[0].attributes.categories?.data, - ["attributes.short"] - ).map((category) => category.attributes.short), + ["attributes"] + ).map((category) => formatCategory(category.attributes.slug)), [format("type", { count: Infinity })]: item.libraryItems.data[0].attributes.metadata?.[0] - ? [prettyItemSubType(item.libraryItems.data[0].attributes.metadata[0])] + ? [formatLibraryItemSubType(item.libraryItems.data[0].attributes.metadata[0])] : [], [format("release_date")]: [ item.libraryItems.data[0].attributes.release_date diff --git a/src/pages/library/[slug]/reader.tsx b/src/pages/library/[slug]/reader.tsx index 54159a3..7637a9f 100644 --- a/src/pages/library/[slug]/reader.tsx +++ b/src/pages/library/[slug]/reader.tsx @@ -593,7 +593,6 @@ export const getStaticProps: GetStaticProps = async (context) => { const { format } = getFormat(context.locale); const item = await sdk.getLibraryItemScans({ slug: context.params && isDefined(context.params.slug) ? context.params.slug.toString() : "", - language_code: context.locale ?? "en", }); if (!item.libraryItems?.data[0]?.attributes || !item.libraryItems.data[0]?.id) return { notFound: true }; @@ -891,7 +890,7 @@ const ScanSet = ({ onClickOnImage, scanSet, id, title, content }: ScanSetProps): {filterHasAttributes(selectedScan.scanners.data, ["id", "attributes"]).map( (scanner) => ( - + ) )} @@ -906,7 +905,7 @@ const ScanSet = ({ onClickOnImage, scanSet, id, title, content }: ScanSetProps): {filterHasAttributes(selectedScan.cleaners.data, ["id", "attributes"]).map( (cleaner) => ( - + ) )} @@ -921,7 +920,7 @@ const ScanSet = ({ onClickOnImage, scanSet, id, title, content }: ScanSetProps): {filterHasAttributes(selectedScan.typesetters.data, ["id", "attributes"]).map( (typesetter) => ( - + ) )} diff --git a/src/pages/library/index.tsx b/src/pages/library/index.tsx index f4c282c..59856b8 100644 --- a/src/pages/library/index.tsx +++ b/src/pages/library/index.tsx @@ -27,7 +27,6 @@ import { import { MeiliIndices, MeiliLibraryItem } from "shared/meilisearch-graphql-typings/meiliTypes"; import { useTypedRouter } from "hooks/useTypedRouter"; import { TranslatedPreviewCard } from "components/PreviewCard"; -import { prettyItemSubType } from "helpers/formatters"; import { isUntangibleGroupItem } from "helpers/libraryItem"; import { PreviewCardCTAs } from "components/Library/PreviewCardCTAs"; import { useLibraryItemUserStatus } from "hooks/useLibraryItemUserStatus"; @@ -70,7 +69,7 @@ interface Props extends AppLayoutRequired {} const Library = (props: Props): JSX.Element => { const hoverable = useDeviceSupportsHover(); - const { format } = useFormat(); + const { format, formatCategory, formatLibraryItemSubType } = useFormat(); const { libraryItemUserStatus } = useLibraryItemUserStatus(); const sortingMethods = useMemo( @@ -414,11 +413,11 @@ const Library = (props: Props): JSX.Element => { keepInfoVisible={keepInfoVisible} topChips={ item.metadata && item.metadata.length > 0 && item.metadata[0] - ? [prettyItemSubType(item.metadata[0])] - : [] + ? [formatLibraryItemSubType(item.metadata[0])] + : undefined } - bottomChips={item.categories?.data.map( - (category) => category.attributes?.short ?? "" + bottomChips={filterHasAttributes(item.categories?.data, ["attributes"]).map( + (category) => formatCategory(category.attributes.slug) )} metadata={{ releaseDate: item.release_date, diff --git a/src/pages/news/index.tsx b/src/pages/news/index.tsx index 7d5133f..20188c3 100644 --- a/src/pages/news/index.tsx +++ b/src/pages/news/index.tsx @@ -56,7 +56,7 @@ const queryParamSchema = z.object({ interface Props extends AppLayoutRequired {} const News = ({ ...otherProps }: Props): JSX.Element => { - const { format } = useFormat(); + const { format, formatCategory } = useFormat(); const hoverable = useDeviceSupportsHover(); const router = useTypedRouter(queryParamSchema); @@ -180,8 +180,8 @@ const News = ({ ...otherProps }: Props): JSX.Element => { thumbnailAspectRatio="3/2" thumbnailForceAspectRatio keepInfoVisible={keepInfoVisible} - bottomChips={item.categories?.data.map( - (category) => category.attributes?.short ?? "" + bottomChips={filterHasAttributes(item.categories?.data, ["attributes"]).map( + (category) => formatCategory(category.attributes.slug) )} metadata={{ releaseDate: item.date, diff --git a/src/pages/wiki/[slug]/index.tsx b/src/pages/wiki/[slug]/index.tsx index 73a9012..df74674 100644 --- a/src/pages/wiki/[slug]/index.tsx +++ b/src/pages/wiki/[slug]/index.tsx @@ -38,7 +38,7 @@ interface Props extends AppLayoutRequired { } const WikiPage = ({ page, ...otherProps }: Props): JSX.Element => { - const { format } = useFormat(); + const { format, formatCategory, formatWikiTag } = useFormat(); const router = useRouter(); const isTerminalMode = useAtomGetter(atoms.layout.terminalMode); const setSubPanelOpened = useAtomSetter(atoms.layout.subPanelOpened); @@ -126,7 +126,10 @@ const WikiPage = ({ page, ...otherProps }: Props): JSX.Element => {
{filterHasAttributes(page.categories.data, ["attributes"]).map((category) => ( - + ))}
@@ -137,12 +140,7 @@ const WikiPage = ({ page, ...otherProps }: Props): JSX.Element => {

{format("tags")}

{filterHasAttributes(page.tags.data, ["attributes"]).map((tag) => ( - + ))}
@@ -180,7 +178,7 @@ const WikiPage = ({ page, ...otherProps }: Props): JSX.Element => { }))} index={index + 1} categories={filterHasAttributes(definition.categories?.data, ["attributes"]).map( - (category) => category.attributes.short + (category) => formatCategory(category.attributes.slug) )} /> @@ -250,24 +248,21 @@ export default WikiPage; export const getStaticProps: GetStaticProps = async (context) => { const sdk = getReadySdk(); - const { format } = getFormat(context.locale); + const { format, formatCategory, formatWikiTag } = getFormat(context.locale); const slug = context.params && isDefined(context.params.slug) ? context.params.slug.toString() : ""; - const page = await sdk.getWikiPage({ - language_code: context.locale ?? "en", - slug: slug, - }); + const page = await sdk.getWikiPage({ slug: slug }); if (!page.wikiPages?.data[0]?.attributes?.translations) return { notFound: true }; const { title, description } = (() => { const chipsGroups = { [format("tags")]: filterHasAttributes(page.wikiPages.data[0].attributes.tags?.data, [ "attributes", - ]).map((tag) => tag.attributes.titles?.[0]?.title ?? prettySlug(tag.attributes.slug)), + ]).map((tag) => formatWikiTag(tag.attributes.slug)), [format("category", { count: Infinity })]: filterHasAttributes( page.wikiPages.data[0].attributes.categories?.data, ["attributes"] - ).map((category) => category.attributes.short), + ).map((category) => formatCategory(category.attributes.slug)), }; if (context.locale && context.locales) { diff --git a/src/pages/wiki/index.tsx b/src/pages/wiki/index.tsx index ee69d35..fc2493d 100644 --- a/src/pages/wiki/index.tsx +++ b/src/pages/wiki/index.tsx @@ -51,10 +51,10 @@ const queryParamSchema = z.object({ interface Props extends AppLayoutRequired {} const Wiki = (props: Props): JSX.Element => { + const { format, formatCategory, formatWikiTag } = useFormat(); const hoverable = useDeviceSupportsHover(); const setSubPanelOpened = useAtomSetter(atoms.layout.subPanelOpened); const closeSubPanel = useCallback(() => setSubPanelOpened(false), [setSubPanelOpened]); - const { format } = useFormat(); const router = useTypedRouter(queryParamSchema); const [query, setQuery] = useState(router.query.query ?? DEFAULT_FILTERS_STATE.query); @@ -201,11 +201,11 @@ const Wiki = (props: Props): JSX.Element => { thumbnailRounded thumbnailForceAspectRatio keepInfoVisible - topChips={filterHasAttributes(item.tags?.data, ["attributes"]).map( - (tag) => tag.attributes.titles?.[0]?.title ?? prettySlug(tag.attributes.slug) + topChips={filterHasAttributes(item.tags?.data, ["attributes"]).map((tag) => + formatWikiTag(tag.attributes.slug) )} bottomChips={filterHasAttributes(item.categories?.data, ["attributes"]).map( - (category) => category.attributes.short + (category) => formatCategory(category.attributes.slug) )} /> ))} diff --git a/src/pages/wiki/weapons/[slug].tsx b/src/pages/wiki/weapons/[slug].tsx index f777cf6..50c54d2 100644 --- a/src/pages/wiki/weapons/[slug].tsx +++ b/src/pages/wiki/weapons/[slug].tsx @@ -64,7 +64,7 @@ const WeaponPreview = ({ weapon }: WeaponPreviewProps): JSX.Element => ( ); const WeaponPage = ({ weapon, primaryName, aliases, ...otherProps }: Props): JSX.Element => { - const { format } = useFormat(); + const { format, formatCategory, formatWeaponType } = useFormat(); const intersectionIds = useMemo( () => filterDefined(weapon.stories).map(({ id }) => `story-${id}`), @@ -91,8 +91,10 @@ const WeaponPage = ({ weapon, primaryName, aliases, ...otherProps }: Props): JSX key={index} url={`#${id}`} title={`Story ${index + 1}`} - subtitle={weapon.stories?.[index]?.categories?.data - .map((category) => category.attributes?.name) + subtitle={filterHasAttributes(weapon.stories?.[index]?.categories?.data, [ + "attributes", + ]) + .map((category) => formatCategory(category.attributes.slug)) .join("・")} active={currentIntersection === index} border @@ -133,6 +135,11 @@ const WeaponPage = ({ weapon, primaryName, aliases, ...otherProps }: Props): JSX @@ -166,10 +173,7 @@ export const getStaticProps: GetStaticProps = async (context) => { const sdk = getReadySdk(); const { format } = getFormat(context.locale); const slug = context.params?.slug ? context.params.slug.toString() : ""; - const weaponResp = await sdk.getWeapon({ - slug: slug, - language_code: context.locale ?? "en", - }); + const weaponResp = await sdk.getWeapon({ slug: slug }); const weapon = weaponResp.weaponStories?.data[0]?.attributes; @@ -227,7 +231,7 @@ interface WeaponStoryProps { } const WeaponStory = ({ story, storyNumber, id }: WeaponStoryProps): JSX.Element => { - const { format } = useFormat(); + const { format, formatCategory } = useFormat(); const [selectedTranslation, LanguageSwitcher, languageSwitcherProps] = useSmartLanguage({ items: story.translations, languageExtractor: useCallback( @@ -241,14 +245,18 @@ const WeaponStory = ({ story, storyNumber, id }: WeaponStoryProps): JSX.Element return ( -

{format("story_x", { x: storyNumber })}

- - {languageSwitcherProps.locales.size > 1 && } +
+

{format("story_x", { x: storyNumber })}

+ {languageSwitcherProps.locales.size > 1 && } +
{story.categories && story.categories.data.length > 0 && (
- {filterHasAttributes(story.categories.data, ["attributes.name"]).map((category) => ( - + {filterHasAttributes(story.categories.data, ["attributes"]).map((category) => ( + ))}
)} diff --git a/src/pages/wiki/weapons/index.tsx b/src/pages/wiki/weapons/index.tsx index 82ea497..909a4b6 100644 --- a/src/pages/wiki/weapons/index.tsx +++ b/src/pages/wiki/weapons/index.tsx @@ -54,7 +54,7 @@ const queryParamSchema = z.object({ interface Props extends AppLayoutRequired {} const Weapons = (props: Props): JSX.Element => { - const { format } = useFormat(); + const { format, formatCategory, formatWeaponType } = useFormat(); const hoverable = useDeviceSupportsHover(); const router = useTypedRouter(queryParamSchema); @@ -190,11 +190,11 @@ const Weapons = (props: Props): JSX.Element => { keepInfoVisible={keepInfoVisible} topChips={ item.type?.data?.attributes?.slug - ? [prettySlug(item.type.data.attributes.slug)] + ? [formatWeaponType(item.type.data.attributes.slug)] : undefined } - bottomChips={filterHasAttributes(item.categories, ["attributes.short"]).map( - (category) => category.attributes.short + bottomChips={filterHasAttributes(item.categories, ["attributes"]).map((category) => + formatCategory(category.attributes.slug) )} /> ))} @@ -203,11 +203,7 @@ const Weapons = (props: Props): JSX.Element => { ); - return ( - <> - - - ); + return ; }; export default Weapons; diff --git a/src/shared/meilisearch-graphql-typings/generated.ts b/src/shared/meilisearch-graphql-typings/generated.ts index 0c437d1..6f2af17 100644 --- a/src/shared/meilisearch-graphql-typings/generated.ts +++ b/src/shared/meilisearch-graphql-typings/generated.ts @@ -98,9 +98,17 @@ export type Category = { name: Scalars["String"]; series?: Maybe; short: Scalars["String"]; + slug: Scalars["String"]; + titles?: Maybe>>; updatedAt?: Maybe; }; +export type CategoryTitlesArgs = { + filters?: InputMaybe; + pagination?: InputMaybe; + sort?: InputMaybe>>; +}; + export type CategoryEntity = { __typename?: "CategoryEntity"; attributes?: Maybe; @@ -127,6 +135,8 @@ export type CategoryFiltersInput = { or?: InputMaybe>>; series?: InputMaybe; short?: InputMaybe; + slug?: InputMaybe; + titles?: InputMaybe; updatedAt?: InputMaybe; }; @@ -134,6 +144,8 @@ export type CategoryInput = { name?: InputMaybe; series?: InputMaybe; short?: InputMaybe; + slug?: InputMaybe; + titles?: InputMaybe>>; }; export type CategoryRelationResponseCollection = { @@ -909,6 +921,13 @@ export type ComponentMetadataAudio = { __typename?: "ComponentMetadataAudio"; id: Scalars["ID"]; subtype?: Maybe; + tracks?: Maybe>>; +}; + +export type ComponentMetadataAudioTracksArgs = { + filters?: InputMaybe; + pagination?: InputMaybe; + sort?: InputMaybe>>; }; export type ComponentMetadataBooks = { @@ -933,6 +952,7 @@ export type ComponentMetadataGame = { demo: Scalars["Boolean"]; id: Scalars["ID"]; interface_languages?: Maybe; + platform?: Maybe; platforms?: Maybe; sub_languages?: Maybe; }; @@ -1036,16 +1056,15 @@ export type ComponentRangeTimeRange = { export type ComponentSetsAudioSet = { __typename?: "ComponentSetsAudioSet"; - audiofile?: Maybe; - dubbers?: Maybe; + dubbers?: Maybe; id: Scalars["ID"]; notes?: Maybe; source_language?: Maybe; status?: Maybe; }; -export type ComponentSetsAudioSetAudiofileArgs = { - filters?: InputMaybe; +export type ComponentSetsAudioSetDubbersArgs = { + filters?: InputMaybe; pagination?: InputMaybe; sort?: InputMaybe>>; }; @@ -1061,8 +1080,7 @@ export type ComponentSetsAudioSetFiltersInput = { }; export type ComponentSetsAudioSetInput = { - audiofile?: InputMaybe>>; - dubbers?: InputMaybe; + dubbers?: InputMaybe>>; id?: InputMaybe; notes?: InputMaybe; source_language?: InputMaybe; @@ -1185,36 +1203,55 @@ export type ComponentSetsTextSetInput = { translators?: InputMaybe>>; }; +export type ComponentSetsTrackSet = { + __typename?: "ComponentSetsTrackSet"; + id: Scalars["ID"]; + slug: Scalars["String"]; + title: Scalars["String"]; +}; + +export type ComponentSetsTrackSetFiltersInput = { + and?: InputMaybe>>; + not?: InputMaybe; + or?: InputMaybe>>; + slug?: InputMaybe; + title?: InputMaybe; +}; + export type ComponentSetsVideoSet = { __typename?: "ComponentSetsVideoSet"; + has_subfile: Scalars["Boolean"]; id: Scalars["ID"]; notes?: Maybe; source_language?: Maybe; status: Enum_Componentsetsvideoset_Status; - subbers?: Maybe; - subfile?: Maybe; - video_url?: Maybe; + subbers?: Maybe; +}; + +export type ComponentSetsVideoSetSubbersArgs = { + filters?: InputMaybe; + pagination?: InputMaybe; + sort?: InputMaybe>>; }; export type ComponentSetsVideoSetFiltersInput = { and?: InputMaybe>>; + has_subfile?: InputMaybe; not?: InputMaybe; notes?: InputMaybe; or?: InputMaybe>>; source_language?: InputMaybe; status?: InputMaybe; subbers?: InputMaybe; - video_url?: InputMaybe; }; export type ComponentSetsVideoSetInput = { + has_subfile?: InputMaybe; id?: InputMaybe; notes?: InputMaybe; source_language?: InputMaybe; status?: InputMaybe; - subbers?: InputMaybe; - subfile?: InputMaybe; - video_url?: InputMaybe; + subbers?: InputMaybe>>; }; export type ComponentSetsWikiSet = { @@ -1287,6 +1324,30 @@ export type ComponentTranslationsBioInput = { language?: InputMaybe; }; +export type ComponentTranslationsCategoriesTitle = { + __typename?: "ComponentTranslationsCategoriesTitle"; + id: Scalars["ID"]; + language?: Maybe; + short?: Maybe; + title?: Maybe; +}; + +export type ComponentTranslationsCategoriesTitleFiltersInput = { + and?: InputMaybe>>; + language?: InputMaybe; + not?: InputMaybe; + or?: InputMaybe>>; + short?: InputMaybe; + title?: InputMaybe; +}; + +export type ComponentTranslationsCategoriesTitleInput = { + id?: InputMaybe; + language?: InputMaybe; + short?: InputMaybe; + title?: InputMaybe; +}; + export type ComponentTranslationsChronicles = { __typename?: "ComponentTranslationsChronicles"; body?: Maybe; @@ -1368,13 +1429,58 @@ export type ComponentTranslationsChronologyItemInput = { title?: InputMaybe; }; +export type ComponentTranslationsGamePlatformsTranslations = { + __typename?: "ComponentTranslationsGamePlatformsTranslations"; + id: Scalars["ID"]; + language?: Maybe; + short?: Maybe; + title?: Maybe; +}; + +export type ComponentTranslationsGamePlatformsTranslationsFiltersInput = { + and?: InputMaybe>>; + language?: InputMaybe; + not?: InputMaybe; + or?: InputMaybe>>; + short?: InputMaybe; + title?: InputMaybe; +}; + +export type ComponentTranslationsGamePlatformsTranslationsInput = { + id?: InputMaybe; + language?: InputMaybe; + short?: InputMaybe; + title?: InputMaybe; +}; + export type ComponentTranslationsGlossaryDefinition = { __typename?: "ComponentTranslationsGlossaryDefinition"; definition?: Maybe; id: Scalars["ID"]; language?: Maybe; + proofreaders?: Maybe; source_language?: Maybe; status: Enum_Componenttranslationsglossarydefinition_Status; + transcribers?: Maybe; + translators?: Maybe; +}; + +export type ComponentTranslationsGlossaryDefinitionProofreadersArgs = { + filters?: InputMaybe; + pagination?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type ComponentTranslationsGlossaryDefinitionTranscribersArgs = { + filters?: InputMaybe; + pagination?: InputMaybe; + sort?: InputMaybe>>; +}; + +export type ComponentTranslationsGlossaryDefinitionTranslatorsArgs = { + filters?: InputMaybe; + pagination?: InputMaybe; + sort?: InputMaybe>>; }; export type ComponentTranslationsGlossaryDefinitionFiltersInput = { @@ -1383,16 +1489,22 @@ export type ComponentTranslationsGlossaryDefinitionFiltersInput = { language?: InputMaybe; not?: InputMaybe; or?: InputMaybe>>; + proofreaders?: InputMaybe; source_language?: InputMaybe; status?: InputMaybe; + transcribers?: InputMaybe; + translators?: InputMaybe; }; export type ComponentTranslationsGlossaryDefinitionInput = { definition?: InputMaybe; id?: InputMaybe; language?: InputMaybe; + proofreaders?: InputMaybe>>; source_language?: InputMaybe; status?: InputMaybe; + transcribers?: InputMaybe>>; + translators?: InputMaybe>>; }; export type ComponentTranslationsGlossaryItem = { @@ -2376,9 +2488,17 @@ export type GamePlatform = { createdAt?: Maybe; name: Scalars["String"]; short: Scalars["String"]; + slug: Scalars["String"]; + titles?: Maybe>>; updatedAt?: Maybe; }; +export type GamePlatformTitlesArgs = { + filters?: InputMaybe; + pagination?: InputMaybe; + sort?: InputMaybe>>; +}; + export type GamePlatformEntity = { __typename?: "GamePlatformEntity"; attributes?: Maybe; @@ -2404,12 +2524,16 @@ export type GamePlatformFiltersInput = { not?: InputMaybe; or?: InputMaybe>>; short?: InputMaybe; + slug?: InputMaybe; + titles?: InputMaybe; updatedAt?: InputMaybe; }; export type GamePlatformInput = { name?: InputMaybe; short?: InputMaybe; + slug?: InputMaybe; + titles?: InputMaybe>>; }; export type GamePlatformRelationResponseCollection = { @@ -2459,14 +2583,17 @@ export type GenericMorph = | ComponentSetsAudioSet | ComponentSetsScanSet | ComponentSetsTextSet + | ComponentSetsTrackSet | ComponentSetsVideoSet | ComponentSetsWikiSet | ComponentSourceUrlSource | ComponentTranslationsAudioSets | ComponentTranslationsBio + | ComponentTranslationsCategoriesTitle | ComponentTranslationsChronicles | ComponentTranslationsChronologyEra | ComponentTranslationsChronologyItem + | ComponentTranslationsGamePlatformsTranslations | ComponentTranslationsGlossaryDefinition | ComponentTranslationsGlossaryItem | ComponentTranslationsLibraryContent @@ -2793,6 +2920,7 @@ export type LibraryItem = { createdAt?: Maybe; descriptions?: Maybe>>; digital: Scalars["Boolean"]; + download_available: Scalars["Boolean"]; gallery?: Maybe; images?: Maybe>>; metadata?: Maybe>>; @@ -2890,6 +3018,7 @@ export type LibraryItemFiltersInput = { createdAt?: InputMaybe; descriptions?: InputMaybe; digital?: InputMaybe; + download_available?: InputMaybe; id?: InputMaybe; images?: InputMaybe; not?: InputMaybe; @@ -2914,6 +3043,7 @@ export type LibraryItemInput = { contents?: InputMaybe>>; descriptions?: InputMaybe>>; digital?: InputMaybe; + download_available?: InputMaybe; gallery?: InputMaybe>>; images?: InputMaybe>>; metadata?: InputMaybe>; @@ -5211,21 +5341,21 @@ export type WebsiteInterface = { archives?: Maybe; archives_description?: Maybe; audio?: Maybe; + author?: Maybe; auto?: Maybe; available_at?: Maybe; + available_at_x?: Maybe; back_matter?: Maybe; binding?: Maybe; book_fold?: Maybe; calculated?: Maybe; category?: Maybe; - change_language?: Maybe; channel?: Maybe; chronicles?: Maybe; chronicles_description?: Maybe; chronicles_short_description?: Maybe; chronology?: Maybe; cleaners?: Maybe; - combine_related_contents?: Maybe; contact_us?: Maybe; content?: Maybe; content_is_not_available?: Maybe; @@ -5243,10 +5373,11 @@ export type WebsiteInterface = { definition_x?: Maybe; description?: Maybe; details?: Maybe; - display_all_items?: Maybe; done?: Maybe; double_page_view?: Maybe; + download_archive?: Maybe; draft?: Maybe; + dubber?: Maybe; email?: Maybe; email_gdpr_notice?: Maybe; empty_folder_message?: Maybe; @@ -5303,13 +5434,15 @@ export type WebsiteInterface = { page_order?: Maybe; paper_texture?: Maybe; paperback?: Maybe; + performance_mode?: Maybe; + performance_mode_tooltip?: Maybe; player_name?: Maybe; player_name_tooltip?: Maybe; previous_content?: Maybe; price?: Maybe; primary_language?: Maybe; pronouns?: Maybe; - proofreaders?: Maybe; + proofreader?: Maybe; quality?: Maybe; read_content?: Maybe; reading_layout?: Maybe; @@ -5327,9 +5460,8 @@ export type WebsiteInterface = { scanlation?: Maybe; scanners?: Maybe; search?: Maybe; - search_title?: Maybe; + search_placeholder?: Maybe; secondary_language?: Maybe; - select_language?: Maybe; select_option_sidebar?: Maybe; send?: Maybe; settings?: Maybe; @@ -5352,6 +5484,7 @@ export type WebsiteInterface = { status_incomplete?: Maybe; status_review?: Maybe; story_x?: Maybe; + subber?: Maybe; subitem?: Maybe; subitem_of_x?: Maybe; subscribers?: Maybe; @@ -5363,10 +5496,10 @@ export type WebsiteInterface = { textual?: Maybe; theme?: Maybe; thickness?: Maybe; - transcribers?: Maybe; + transcriber?: Maybe; transcript_notice?: Maybe; translation_notice?: Maybe; - translators?: Maybe; + translator?: Maybe; type?: Maybe; type_information?: Maybe; typesetters?: Maybe; @@ -5377,6 +5510,7 @@ export type WebsiteInterface = { video?: Maybe; videos?: Maybe; view_on?: Maybe; + view_on_x?: Maybe; view_scans?: Maybe; want_it?: Maybe; watch_content?: Maybe; @@ -5417,21 +5551,21 @@ export type WebsiteInterfaceFiltersInput = { archives?: InputMaybe; archives_description?: InputMaybe; audio?: InputMaybe; + author?: InputMaybe; auto?: InputMaybe; available_at?: InputMaybe; + available_at_x?: InputMaybe; back_matter?: InputMaybe; binding?: InputMaybe; book_fold?: InputMaybe; calculated?: InputMaybe; category?: InputMaybe; - change_language?: InputMaybe; channel?: InputMaybe; chronicles?: InputMaybe; chronicles_description?: InputMaybe; chronicles_short_description?: InputMaybe; chronology?: InputMaybe; cleaners?: InputMaybe; - combine_related_contents?: InputMaybe; contact_us?: InputMaybe; content?: InputMaybe; content_is_not_available?: InputMaybe; @@ -5449,10 +5583,11 @@ export type WebsiteInterfaceFiltersInput = { definition_x?: InputMaybe; description?: InputMaybe; details?: InputMaybe; - display_all_items?: InputMaybe; done?: InputMaybe; double_page_view?: InputMaybe; + download_archive?: InputMaybe; draft?: InputMaybe; + dubber?: InputMaybe; email?: InputMaybe; email_gdpr_notice?: InputMaybe; empty_folder_message?: InputMaybe; @@ -5512,13 +5647,15 @@ export type WebsiteInterfaceFiltersInput = { page_order?: InputMaybe; paper_texture?: InputMaybe; paperback?: InputMaybe; + performance_mode?: InputMaybe; + performance_mode_tooltip?: InputMaybe; player_name?: InputMaybe; player_name_tooltip?: InputMaybe; previous_content?: InputMaybe; price?: InputMaybe; primary_language?: InputMaybe; pronouns?: InputMaybe; - proofreaders?: InputMaybe; + proofreader?: InputMaybe; quality?: InputMaybe; read_content?: InputMaybe; reading_layout?: InputMaybe; @@ -5536,9 +5673,8 @@ export type WebsiteInterfaceFiltersInput = { scanlation?: InputMaybe; scanners?: InputMaybe; search?: InputMaybe; - search_title?: InputMaybe; + search_placeholder?: InputMaybe; secondary_language?: InputMaybe; - select_language?: InputMaybe; select_option_sidebar?: InputMaybe; send?: InputMaybe; settings?: InputMaybe; @@ -5561,6 +5697,7 @@ export type WebsiteInterfaceFiltersInput = { status_incomplete?: InputMaybe; status_review?: InputMaybe; story_x?: InputMaybe; + subber?: InputMaybe; subitem?: InputMaybe; subitem_of_x?: InputMaybe; subscribers?: InputMaybe; @@ -5572,10 +5709,10 @@ export type WebsiteInterfaceFiltersInput = { textual?: InputMaybe; theme?: InputMaybe; thickness?: InputMaybe; - transcribers?: InputMaybe; + transcriber?: InputMaybe; transcript_notice?: InputMaybe; translation_notice?: InputMaybe; - translators?: InputMaybe; + translator?: InputMaybe; type?: InputMaybe; type_information?: InputMaybe; typesetters?: InputMaybe; @@ -5586,6 +5723,7 @@ export type WebsiteInterfaceFiltersInput = { video?: InputMaybe; videos?: InputMaybe; view_on?: InputMaybe; + view_on_x?: InputMaybe; view_scans?: InputMaybe; want_it?: InputMaybe; watch_content?: InputMaybe; @@ -5608,21 +5746,21 @@ export type WebsiteInterfaceInput = { archives?: InputMaybe; archives_description?: InputMaybe; audio?: InputMaybe; + author?: InputMaybe; auto?: InputMaybe; available_at?: InputMaybe; + available_at_x?: InputMaybe; back_matter?: InputMaybe; binding?: InputMaybe; book_fold?: InputMaybe; calculated?: InputMaybe; category?: InputMaybe; - change_language?: InputMaybe; channel?: InputMaybe; chronicles?: InputMaybe; chronicles_description?: InputMaybe; chronicles_short_description?: InputMaybe; chronology?: InputMaybe; cleaners?: InputMaybe; - combine_related_contents?: InputMaybe; contact_us?: InputMaybe; content?: InputMaybe; content_is_not_available?: InputMaybe; @@ -5639,10 +5777,11 @@ export type WebsiteInterfaceInput = { definition_x?: InputMaybe; description?: InputMaybe; details?: InputMaybe; - display_all_items?: InputMaybe; done?: InputMaybe; double_page_view?: InputMaybe; + download_archive?: InputMaybe; draft?: InputMaybe; + dubber?: InputMaybe; email?: InputMaybe; email_gdpr_notice?: InputMaybe; empty_folder_message?: InputMaybe; @@ -5699,13 +5838,15 @@ export type WebsiteInterfaceInput = { page_order?: InputMaybe; paper_texture?: InputMaybe; paperback?: InputMaybe; + performance_mode?: InputMaybe; + performance_mode_tooltip?: InputMaybe; player_name?: InputMaybe; player_name_tooltip?: InputMaybe; previous_content?: InputMaybe; price?: InputMaybe; primary_language?: InputMaybe; pronouns?: InputMaybe; - proofreaders?: InputMaybe; + proofreader?: InputMaybe; quality?: InputMaybe; read_content?: InputMaybe; reading_layout?: InputMaybe; @@ -5723,9 +5864,8 @@ export type WebsiteInterfaceInput = { scanlation?: InputMaybe; scanners?: InputMaybe; search?: InputMaybe; - search_title?: InputMaybe; + search_placeholder?: InputMaybe; secondary_language?: InputMaybe; - select_language?: InputMaybe; select_option_sidebar?: InputMaybe; send?: InputMaybe; settings?: InputMaybe; @@ -5748,6 +5888,7 @@ export type WebsiteInterfaceInput = { status_incomplete?: InputMaybe; status_review?: InputMaybe; story_x?: InputMaybe; + subber?: InputMaybe; subitem?: InputMaybe; subitem_of_x?: InputMaybe; subscribers?: InputMaybe; @@ -5759,10 +5900,10 @@ export type WebsiteInterfaceInput = { textual?: InputMaybe; theme?: InputMaybe; thickness?: InputMaybe; - transcribers?: InputMaybe; + transcriber?: InputMaybe; transcript_notice?: InputMaybe; translation_notice?: InputMaybe; - translators?: InputMaybe; + translator?: InputMaybe; type?: InputMaybe; type_information?: InputMaybe; typesetters?: InputMaybe; @@ -5772,6 +5913,7 @@ export type WebsiteInterfaceInput = { video?: InputMaybe; videos?: InputMaybe; view_on?: InputMaybe; + view_on_x?: InputMaybe; view_scans?: InputMaybe; want_it?: InputMaybe; watch_content?: InputMaybe; @@ -5952,22 +6094,14 @@ export type ContentAttributesFragment = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; name: string; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; type?: { __typename?: "ContentTypeEntityResponse"; data?: { __typename?: "ContentTypeEntity"; - attributes?: { - __typename?: "ContentType"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "ContentType"; slug: string } | null; } | null; } | null; thumbnail?: { @@ -6046,8 +6180,7 @@ export type LibraryItemAttributesFragment = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; name: string; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; metadata?: Array< @@ -6057,14 +6190,7 @@ export type LibraryItemAttributesFragment = { __typename?: "AudioSubtypeEntityResponse"; data?: { __typename?: "AudioSubtypeEntity"; - attributes?: { - __typename?: "AudioSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "AudioSubtype"; slug: string } | null; } | null; } | null; } @@ -6074,26 +6200,18 @@ export type LibraryItemAttributesFragment = { __typename?: "TextualSubtypeEntityResponse"; data?: { __typename?: "TextualSubtypeEntity"; - attributes?: { - __typename?: "TextualSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "TextualSubtype"; slug: string } | null; } | null; } | null; } | { __typename: "ComponentMetadataGame"; - platforms?: { - __typename?: "GamePlatformRelationResponseCollection"; - data: Array<{ + platform?: { + __typename?: "GamePlatformEntityResponse"; + data?: { __typename?: "GamePlatformEntity"; - id?: string | null; - attributes?: { __typename?: "GamePlatform"; short: string } | null; - }>; + attributes?: { __typename?: "GamePlatform"; slug: string } | null; + } | null; } | null; } | { @@ -6102,28 +6220,14 @@ export type LibraryItemAttributesFragment = { __typename?: "GroupSubtypeEntityResponse"; data?: { __typename?: "GroupSubtypeEntity"; - attributes?: { - __typename?: "GroupSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "GroupSubtype"; slug: string } | null; } | null; } | null; subitems_type?: { __typename?: "MetadataTypeEntityResponse"; data?: { __typename?: "MetadataTypeEntity"; - attributes?: { - __typename?: "MetadataType"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "MetadataType"; slug: string } | null; } | null; } | null; } @@ -6134,14 +6238,7 @@ export type LibraryItemAttributesFragment = { __typename?: "VideoSubtypeEntityResponse"; data?: { __typename?: "VideoSubtypeEntity"; - attributes?: { - __typename?: "VideoSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "VideoSubtype"; slug: string } | null; } | null; } | null; } @@ -6164,8 +6261,7 @@ export type PostAttributesFragment = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; thumbnail?: { @@ -6259,21 +6355,7 @@ export type WeaponAttributesFragment = { data?: { __typename?: "WeaponStoryTypeEntity"; id?: string | null; - attributes?: { - __typename?: "WeaponStoryType"; - slug: string; - translations?: Array<{ - __typename?: "ComponentTranslationsWeaponStoryType"; - name?: string | null; - language?: { - __typename?: "LanguageEntityResponse"; - data?: { - __typename?: "LanguageEntity"; - attributes?: { __typename?: "Language"; code: string } | null; - } | null; - } | null; - } | null> | null; - } | null; + attributes?: { __typename?: "WeaponStoryType"; slug: string } | null; } | null; } | null; name?: Array<{ @@ -6295,8 +6377,7 @@ export type WeaponAttributesFragment = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; translations?: Array<{ @@ -6340,8 +6421,7 @@ export type WikiPageAttributesFragment = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; name: string; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; definitions?: Array<{ @@ -6362,22 +6442,7 @@ export type WikiPageAttributesFragment = { __typename?: "WikiPagesTagRelationResponseCollection"; data: Array<{ __typename?: "WikiPagesTagEntity"; - id?: string | null; - attributes?: { - __typename?: "WikiPagesTag"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - language?: { - __typename?: "LanguageEntityResponse"; - data?: { - __typename?: "LanguageEntity"; - attributes?: { __typename?: "Language"; code: string } | null; - } | null; - } | null; - } | null> | null; - } | null; + attributes?: { __typename?: "WikiPagesTag"; slug: string } | null; }>; } | null; translations?: Array<{ @@ -6433,22 +6498,14 @@ export type GetContentQuery = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; name: string; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; type?: { __typename?: "ContentTypeEntityResponse"; data?: { __typename?: "ContentTypeEntity"; - attributes?: { - __typename?: "ContentType"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "ContentType"; slug: string } | null; } | null; } | null; thumbnail?: { @@ -6503,22 +6560,14 @@ export type GetContentsQuery = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; name: string; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; type?: { __typename?: "ContentTypeEntityResponse"; data?: { __typename?: "ContentTypeEntity"; - attributes?: { - __typename?: "ContentType"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "ContentType"; slug: string } | null; } | null; } | null; thumbnail?: { @@ -6611,8 +6660,7 @@ export type GetLibraryItemQuery = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; name: string; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; metadata?: Array< @@ -6622,14 +6670,7 @@ export type GetLibraryItemQuery = { __typename?: "AudioSubtypeEntityResponse"; data?: { __typename?: "AudioSubtypeEntity"; - attributes?: { - __typename?: "AudioSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "AudioSubtype"; slug: string } | null; } | null; } | null; } @@ -6639,26 +6680,18 @@ export type GetLibraryItemQuery = { __typename?: "TextualSubtypeEntityResponse"; data?: { __typename?: "TextualSubtypeEntity"; - attributes?: { - __typename?: "TextualSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "TextualSubtype"; slug: string } | null; } | null; } | null; } | { __typename: "ComponentMetadataGame"; - platforms?: { - __typename?: "GamePlatformRelationResponseCollection"; - data: Array<{ + platform?: { + __typename?: "GamePlatformEntityResponse"; + data?: { __typename?: "GamePlatformEntity"; - id?: string | null; - attributes?: { __typename?: "GamePlatform"; short: string } | null; - }>; + attributes?: { __typename?: "GamePlatform"; slug: string } | null; + } | null; } | null; } | { @@ -6667,28 +6700,14 @@ export type GetLibraryItemQuery = { __typename?: "GroupSubtypeEntityResponse"; data?: { __typename?: "GroupSubtypeEntity"; - attributes?: { - __typename?: "GroupSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "GroupSubtype"; slug: string } | null; } | null; } | null; subitems_type?: { __typename?: "MetadataTypeEntityResponse"; data?: { __typename?: "MetadataTypeEntity"; - attributes?: { - __typename?: "MetadataType"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "MetadataType"; slug: string } | null; } | null; } | null; } @@ -6699,14 +6718,7 @@ export type GetLibraryItemQuery = { __typename?: "VideoSubtypeEntityResponse"; data?: { __typename?: "VideoSubtypeEntity"; - attributes?: { - __typename?: "VideoSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "VideoSubtype"; slug: string } | null; } | null; } | null; } @@ -6786,8 +6798,7 @@ export type GetLibraryItemsQuery = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; name: string; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; metadata?: Array< @@ -6797,14 +6808,7 @@ export type GetLibraryItemsQuery = { __typename?: "AudioSubtypeEntityResponse"; data?: { __typename?: "AudioSubtypeEntity"; - attributes?: { - __typename?: "AudioSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "AudioSubtype"; slug: string } | null; } | null; } | null; } @@ -6814,26 +6818,18 @@ export type GetLibraryItemsQuery = { __typename?: "TextualSubtypeEntityResponse"; data?: { __typename?: "TextualSubtypeEntity"; - attributes?: { - __typename?: "TextualSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "TextualSubtype"; slug: string } | null; } | null; } | null; } | { __typename: "ComponentMetadataGame"; - platforms?: { - __typename?: "GamePlatformRelationResponseCollection"; - data: Array<{ + platform?: { + __typename?: "GamePlatformEntityResponse"; + data?: { __typename?: "GamePlatformEntity"; - id?: string | null; - attributes?: { __typename?: "GamePlatform"; short: string } | null; - }>; + attributes?: { __typename?: "GamePlatform"; slug: string } | null; + } | null; } | null; } | { @@ -6842,28 +6838,14 @@ export type GetLibraryItemsQuery = { __typename?: "GroupSubtypeEntityResponse"; data?: { __typename?: "GroupSubtypeEntity"; - attributes?: { - __typename?: "GroupSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "GroupSubtype"; slug: string } | null; } | null; } | null; subitems_type?: { __typename?: "MetadataTypeEntityResponse"; data?: { __typename?: "MetadataTypeEntity"; - attributes?: { - __typename?: "MetadataType"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "MetadataType"; slug: string } | null; } | null; } | null; } @@ -6874,14 +6856,7 @@ export type GetLibraryItemsQuery = { __typename?: "VideoSubtypeEntityResponse"; data?: { __typename?: "VideoSubtypeEntity"; - attributes?: { - __typename?: "VideoSubtype"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - } | null> | null; - } | null; + attributes?: { __typename?: "VideoSubtype"; slug: string } | null; } | null; } | null; } @@ -6918,8 +6893,7 @@ export type GetPostQuery = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; thumbnail?: { @@ -6993,8 +6967,7 @@ export type GetPostsQuery = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; thumbnail?: { @@ -7151,21 +7124,7 @@ export type GetWeaponQuery = { data?: { __typename?: "WeaponStoryTypeEntity"; id?: string | null; - attributes?: { - __typename?: "WeaponStoryType"; - slug: string; - translations?: Array<{ - __typename?: "ComponentTranslationsWeaponStoryType"; - name?: string | null; - language?: { - __typename?: "LanguageEntityResponse"; - data?: { - __typename?: "LanguageEntity"; - attributes?: { __typename?: "Language"; code: string } | null; - } | null; - } | null; - } | null> | null; - } | null; + attributes?: { __typename?: "WeaponStoryType"; slug: string } | null; } | null; } | null; name?: Array<{ @@ -7187,8 +7146,7 @@ export type GetWeaponQuery = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; translations?: Array<{ @@ -7245,21 +7203,7 @@ export type GetWeaponsQuery = { data?: { __typename?: "WeaponStoryTypeEntity"; id?: string | null; - attributes?: { - __typename?: "WeaponStoryType"; - slug: string; - translations?: Array<{ - __typename?: "ComponentTranslationsWeaponStoryType"; - name?: string | null; - language?: { - __typename?: "LanguageEntityResponse"; - data?: { - __typename?: "LanguageEntity"; - attributes?: { __typename?: "Language"; code: string } | null; - } | null; - } | null; - } | null> | null; - } | null; + attributes?: { __typename?: "WeaponStoryType"; slug: string } | null; } | null; } | null; name?: Array<{ @@ -7281,8 +7225,7 @@ export type GetWeaponsQuery = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; translations?: Array<{ @@ -7340,8 +7283,7 @@ export type GetWikiPageQuery = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; name: string; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; definitions?: Array<{ @@ -7362,22 +7304,7 @@ export type GetWikiPageQuery = { __typename?: "WikiPagesTagRelationResponseCollection"; data: Array<{ __typename?: "WikiPagesTagEntity"; - id?: string | null; - attributes?: { - __typename?: "WikiPagesTag"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - language?: { - __typename?: "LanguageEntityResponse"; - data?: { - __typename?: "LanguageEntity"; - attributes?: { __typename?: "Language"; code: string } | null; - } | null; - } | null; - } | null> | null; - } | null; + attributes?: { __typename?: "WikiPagesTag"; slug: string } | null; }>; } | null; translations?: Array<{ @@ -7433,8 +7360,7 @@ export type GetWikiPagesQuery = { __typename?: "CategoryRelationResponseCollection"; data: Array<{ __typename?: "CategoryEntity"; - id?: string | null; - attributes?: { __typename?: "Category"; name: string; short: string } | null; + attributes?: { __typename?: "Category"; slug: string } | null; }>; } | null; definitions?: Array<{ @@ -7455,22 +7381,7 @@ export type GetWikiPagesQuery = { __typename?: "WikiPagesTagRelationResponseCollection"; data: Array<{ __typename?: "WikiPagesTagEntity"; - id?: string | null; - attributes?: { - __typename?: "WikiPagesTag"; - slug: string; - titles?: Array<{ - __typename?: "ComponentTranslationsSimpleTitle"; - title: string; - language?: { - __typename?: "LanguageEntityResponse"; - data?: { - __typename?: "LanguageEntity"; - attributes?: { __typename?: "Language"; code: string } | null; - } | null; - } | null; - } | null> | null; - } | null; + attributes?: { __typename?: "WikiPagesTag"; slug: string } | null; }>; } | null; translations?: Array<{ @@ -7561,10 +7472,8 @@ export const ContentAttributesFragmentDoc = gql` } categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -7572,9 +7481,6 @@ export const ContentAttributesFragmentDoc = gql` data { attributes { slug - titles(filters: { language: { code: { eq: "en" } } }) { - title - } } } } @@ -7641,10 +7547,8 @@ export const LibraryItemAttributesFragmentDoc = gql` } categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -7655,19 +7559,15 @@ export const LibraryItemAttributesFragmentDoc = gql` data { attributes { slug - titles(filters: { language: { code: { eq: "en" } } }) { - title - } } } } } ... on ComponentMetadataGame { - platforms(pagination: { limit: -1 }) { + platform { data { - id attributes { - short + slug } } } @@ -7677,9 +7577,6 @@ export const LibraryItemAttributesFragmentDoc = gql` data { attributes { slug - titles(filters: { language: { code: { eq: "en" } } }) { - title - } } } } @@ -7689,9 +7586,6 @@ export const LibraryItemAttributesFragmentDoc = gql` data { attributes { slug - titles(filters: { language: { code: { eq: "en" } } }) { - title - } } } } @@ -7701,9 +7595,6 @@ export const LibraryItemAttributesFragmentDoc = gql` data { attributes { slug - titles(filters: { language: { code: { eq: "en" } } }) { - title - } } } } @@ -7711,9 +7602,6 @@ export const LibraryItemAttributesFragmentDoc = gql` data { attributes { slug - titles(filters: { language: { code: { eq: "en" } } }) { - title - } } } } @@ -7733,9 +7621,8 @@ export const PostAttributesFragmentDoc = gql` } categories(pagination: { limit: -1 }) { data { - id attributes { - short + slug } } } @@ -7806,16 +7693,6 @@ export const WeaponAttributesFragmentDoc = gql` id attributes { slug - translations(filters: { language: { code: { eq: "en" } } }) { - name - language { - data { - attributes { - code - } - } - } - } } } } @@ -7835,9 +7712,8 @@ export const WeaponAttributesFragmentDoc = gql` id categories(pagination: { limit: -1 }) { data { - id attributes { - short + slug } } } @@ -7872,10 +7748,8 @@ export const WikiPageAttributesFragmentDoc = gql` } categories(pagination: { limit: -1 }) { data { - id attributes { - name - short + slug } } } @@ -7893,19 +7767,8 @@ export const WikiPageAttributesFragmentDoc = gql` } tags(pagination: { limit: -1 }) { data { - id attributes { slug - titles(filters: { language: { code: { eq: "en" } } }) { - language { - data { - attributes { - code - } - } - } - title - } } } } diff --git a/src/types/types.ts b/src/types/types.ts index 9a41097..af15539 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -73,3 +73,39 @@ export enum LibraryItemUserStatus { Want = 1, Have = 2, } + +// ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ + +type LibraryItemMetadataSubType = { + data?: { + attributes?: { + slug: string; + } | null; + } | null; +} | null; + +export type LibraryItemMetadata = + | { + __typename: "ComponentMetadataAudio"; + subtype?: LibraryItemMetadataSubType; + } + | { + __typename: "ComponentMetadataBooks"; + subtype?: LibraryItemMetadataSubType; + } + | { + __typename: "ComponentMetadataGame"; + platform?: LibraryItemMetadataSubType; + } + | { + __typename: "ComponentMetadataGroup"; + subtype?: LibraryItemMetadataSubType; + subitems_type?: LibraryItemMetadataSubType; + } + | { + __typename: "ComponentMetadataVideo"; + subtype?: LibraryItemMetadataSubType; + } + | { __typename: "ComponentMetadataOther" } + | { __typename: "Error" } + | null;