this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

✨ Allow translating attribute values

+97 -35
+5 -1
components/gallery.templ
··· 32 32 document.addEventListener("DOMContentLoaded", () => { 33 33 works = Array.from(document.querySelectorAll("." + galleryClass + " [data-work]")); 34 34 35 - console.log(works.map(w => Object.assign({}, w.dataset))) 35 + console.log(works.map(w => { 36 + var result = Object.assign({}, w.dataset) 37 + result.tags = result.tags.split(",").join(' ') 38 + return result 39 + })) 36 40 37 41 document.searcher = new Fuse(works.map(w => Object.assign({}, w.dataset)), { 38 42 keys: ['work', 'title', 'tags'],
+1 -1
components/ui.templ
··· 53 53 "background-color": "lightgray", 54 54 }) 55 55 <img src={ string(shared.Asset("icons/magnifying_glass.svg")) }/> 56 - <input name="q" oninput={ onInput(searchBarInput().ClassName()) } type="text" class={ searchBarInput() } i18n:placeholder="Search"/> 56 + <input i18n-attrs name="q" oninput={ onInput(searchBarInput().ClassName()) } type="text" class={ searchBarInput() } i18n:placeholder="Search"/> 57 57 </label> 58 58 }
+2 -1
components/work_card.templ
··· 98 98 } 99 99 </style> 100 100 <article 101 + i18n-attrs 101 102 data-work={ work.ID } 102 103 data-title={ work.Content[language].Title.String() } 103 - data-tags={ strings.Join(work.Metadata.Tags, " ") } 104 + i18n:commas:data-tags={ strings.Join(work.Metadata.Tags, ",") } 104 105 class={ "work", card() } 105 106 data-no-thumb?={ ThumbPath(work, language) == "http://localhost:8080/" } 106 107 data-primary={ shared.Color(work.Colors(language).Primary) }
+60 -6
i18n.go
··· 126 126 } 127 127 } 128 128 }) 129 + doc.Find("[i18n-attrs]").Each(func(_ int, element *goquery.Selection) { 130 + element.RemoveAttr("i18n-attrs") 131 + // find all attributes that start with "i18n:" 132 + for _, attribute := range element.Nodes[0].Attr { 133 + if !strings.HasPrefix(attribute.Key, "i18n:") { 134 + continue 135 + } 136 + if strings.HasPrefix(attribute.Key, "i18n:commas:") { 137 + // Multi-valued attributes 138 + translated := attribute.Val 139 + if t.language != SourceLanguage { 140 + translated = "" 141 + for _, val := range strings.Split(attribute.Val, ",") { 142 + translatedItem, err := t.GetTranslation(val, "") 143 + if err != nil { 144 + color.Yellow("[%s] Missing translation for %q", t.language, val) 145 + t.missingMessages = append(t.missingMessages, po.Message{ 146 + MsgId: val, 147 + MsgContext: "", 148 + }) 149 + translatedItem = val 150 + } 151 + translated += "," + translatedItem 152 + } 153 + translated = strings.Trim(translated, ",") 154 + } 155 + element.RemoveAttr(attribute.Key) 156 + element.SetAttr(strings.TrimPrefix(attribute.Key, "i18n:commas:"), translated) 157 + } else { 158 + // Translate the attribute 159 + translated := attribute.Val 160 + if t.language != SourceLanguage { 161 + var err error 162 + translated, err = t.GetTranslation(attribute.Val, "") 163 + if err != nil { 164 + color.Yellow("[%s] Missing translation for %q", t.language, attribute.Val) 165 + t.missingMessages = append(t.missingMessages, po.Message{ 166 + MsgId: attribute.Val, 167 + MsgContext: "", 168 + }) 169 + translated = attribute.Val 170 + } 171 + } 172 + element.RemoveAttr(attribute.Key) 173 + element.SetAttr(strings.TrimPrefix(attribute.Key, "i18n:"), translated) 174 + } 175 + } 176 + }) 129 177 htmlString, _ := doc.Html() 130 178 htmlString = strings.ReplaceAll(htmlString, "<i18n>", "") 131 179 htmlString = strings.ReplaceAll(htmlString, "</i18n>", "") ··· 139 187 translationsFilepath := fmt.Sprintf("i18n/%s.po", languageCode) 140 188 poFile, err := po.LoadFile(translationsFilepath) 141 189 if err != nil { 142 - color.Yellow("[%s] Couldn't load translations: %s", languageCode, err) 143 - err = WriteEmptyPOFile(languageCode) 144 - if err != nil { 145 - return nil, fmt.Errorf("while writing empty PO file: %w", err) 190 + if os.IsNotExist(err) { 191 + color.Yellow("[%s] Missing translation file for %s", languageCode, err) 192 + err = WriteEmptyPOFile(languageCode) 193 + if err != nil { 194 + return nil, fmt.Errorf("while writing empty PO file: %w", err) 195 + } 196 + return LoadTranslations(languages) 197 + } else { 198 + return nil, fmt.Errorf("while loading translations for %s: %w", languageCode, err) 146 199 } 147 - 148 - return LoadTranslations(languages) 149 200 } else { 150 201 translations[languageCode] = &Translations{ 151 202 poFile: *poFile, ··· 262 313 // GetTranslation returns the msgstr corresponding to msgid and msgctxt from the .po file 263 314 // If not found, it returns an error 264 315 func (t Translations) GetTranslation(msgid string, msgctxt string) (string, error) { 316 + if msgid == "" { 317 + return "", nil 318 + } 265 319 t.seenMessages.Add(msgid + msgctxt) 266 320 for _, message := range t.poFile.Messages { 267 321 if message.MsgId == msgid && message.MsgStr != "" && message.MsgContext == msgctxt {
+2 -2
i18n/fr-unused-messages.yaml
··· 1 - # Generated at 2023-12-23 18:28:11.936834364 +0100 CET m=+0.310897677 1 + # Generated at 2023-12-24 15:16:17.424568197 +0100 CET m=+0.334085318 2 2 - "%s’s logo" 3 3 - "%v-day streak on Duolingo, %v league" 4 4 - "1104<sup>th</sup>" ··· 46 46 - "This page does not exist (anymore)" 47 47 - "Unknown error" 48 48 - "Unknown year" 49 + - "Works" 49 50 - "about" 50 51 - "about me" 51 52 - "all" ··· 102 103 - "what" 103 104 - "work in progress" 104 105 - "work time tracked by <a href=\"https://wakatime.com\">WakaTime</a>" 105 - - "works" 106 106 - "works by tag" 107 107 - "works made with" 108 108 - "works made with %s"
+27 -24
i18n/fr.po
··· 12 12 "Content-Transfer-Encoding: 8bit\n" 13 13 "X-Generator: Poedit 3.4.1\n" 14 14 15 + msgid "Search" 16 + msgstr "Rechercher" 17 + 15 18 msgid "%s’s logo" 16 19 msgstr "Logo de %s" 17 20 ··· 77 80 78 81 msgid "A high-quality typesetting & document preparation system" 79 82 msgstr "Un système de composition et de préparation des documents de haute qualité" 83 + 84 + msgid "A human friendly data serialization standard for all programming languages" 85 + msgstr "Une norme de sérialisation des données pour tous les langages de programmation" 86 + 87 + msgid "A language empowering everyone to build reliable and efficient software" 88 + msgstr "Un langage permettant à chacun de construire des logiciels fiables et efficaces" 89 + 90 + msgid "A language for generating UML diagrams from textual descriptions" 91 + msgstr "Un langage permettant de générer des diagrammes UML à partir de descriptions textuelles" 80 92 81 93 msgid "A simple cross-platform library to create graphical user interfaces in [Go](/using/go) that work on Android, iOS, Linux, MacOS and Windows." 82 94 msgstr "Une bibliothèque multiplateforme simple pour créer des interfaces graphiques en [Go](/using/go) qui fonctionnent sur Android, iOS, Linux, MacOS et Windows." ··· 90 102 msgid "Get my resume" 91 103 msgstr "Voir mon CV" 92 104 93 - msgid "A human friendly data serialization standard for all programming languages" 94 - msgstr "Une norme de sérialisation des données pour tous les langages de programmation" 95 - 96 - msgid "A language empowering everyone to build reliable and efficient software" 97 - msgstr "Un langage permettant à chacun de construire des logiciels fiables et efficaces" 98 - 99 - msgid "A language for generating UML diagrams from textual descriptions" 100 - msgstr "Un langage permettant de générer des diagrammes UML à partir de descriptions textuelles" 101 - 102 105 msgid "A language which compiles to JavaScript that adds many features to assist in functional style programming. LiveScript is an indirect descendant of CoffeeScript, with which it has much compatibility." 103 106 msgstr "Un langage qui se compile en JavaScript et qui ajoute de nombreuses fonctionnalités pour aider à la programmation de style fonctionnel. LiveScript est un descendant indirect de CoffeeScript, avec lequel il a une grande compatibilité." 104 107 ··· 141 144 msgid "A programming language that compiles to JavaScript. It adds syntactic sugar inspired by Ruby, Python and Haskell in an effort to enhance JavaScript's brevity and readability. Specific additional features include list comprehension and destructuring assignment" 142 145 msgstr "Un langage de programmation qui se compile en JavaScript. Il ajoute du sucre syntactique inspiré de Ruby, Python et Haskell dans le but d'améliorer la brièveté et la lisibilité de JavaScript. Les caractéristiques supplémentaires spécifiques comprennent la définition de listes en compréhension et l'affectation par déstructuration" 143 146 147 + msgid "A programming language that compiles to JavaScript. It adds syntactic sugar inspired by Ruby, Python and Haskell in an effort to enhance JavaScript’s brevity and readability. Specific additional features include list comprehension and destructuring assignment" 148 + msgstr "Un langage de programmation qui se compile en JavaScript. Il ajoute du sucre syntaxique inspiré de Ruby, Python et Haskell dans le but d'améliorer la brièveté et la lisibilité de JavaScript. Les fonctionnalités supplémentaires spécifiques incluent la compréhension de liste et l'affectation par décomposition" 149 + 150 + msgid "A programming language that lets you work quickly and integrate systems more effectively" 151 + msgstr "Un langage de programmation permettant de travailler rapidement et d'intégrer des systèmes plus efficacement" 152 + 153 + msgid "A progressive Node.js framework for building efficient, reliable and scalable server-side applications" 154 + msgstr "Un framework Node.js progressif pour construire des applications côté serveur efficaces, fiables et évolutives" 155 + 156 + msgid "A radical new approach to building user interfaces. Whereas traditional frameworks like React and Vue do the bulk of their work in the browser, Svelte shifts that work into a compile step that happens when the app is built" 157 + msgstr "Une approche radicalement nouvelle de la construction d'interfaces utilisateurs. Alors que les frameworks traditionnels comme React et Vue font l'essentiel de leur travail dans le navigateur, Svelte transforme ce travail en une étape de compilation qui se produit lors de la création de l'application" 158 + 144 159 msgid "Hi! I'm Ewen Le Bihan." 145 160 msgstr "Hey! Je suis Ewen Le Bihan." 146 161 ··· 167 182 168 183 msgid "web extension" 169 184 msgstr "extension pour navigateur" 170 - 171 - msgid "A programming language that compiles to JavaScript. It adds syntactic sugar inspired by Ruby, Python and Haskell in an effort to enhance JavaScript’s brevity and readability. Specific additional features include list comprehension and destructuring assignment" 172 - msgstr "Un langage de programmation qui se compile en JavaScript. Il ajoute du sucre syntaxique inspiré de Ruby, Python et Haskell dans le but d'améliorer la brièveté et la lisibilité de JavaScript. Les fonctionnalités supplémentaires spécifiques incluent la compréhension de liste et l'affectation par décomposition" 173 - 174 - msgid "A programming language that lets you work quickly and integrate systems more effectively" 175 - msgstr "Un langage de programmation permettant de travailler rapidement et d'intégrer des systèmes plus efficacement" 176 - 177 - msgid "A progressive Node.js framework for building efficient, reliable and scalable server-side applications" 178 - msgstr "Un framework Node.js progressif pour construire des applications côté serveur efficaces, fiables et évolutives" 179 - 180 - msgid "A radical new approach to building user interfaces. Whereas traditional frameworks like React and Vue do the bulk of their work in the browser, Svelte shifts that work into a compile step that happens when the app is built" 181 - msgstr "Une approche radicalement nouvelle de la construction d'interfaces utilisateurs. Alors que les frameworks traditionnels comme React et Vue font l'essentiel de leur travail dans le navigateur, Svelte transforme ce travail en une étape de compilation qui se produit lors de la création de l'application" 182 185 183 186 msgid "A radical new approach to building user interfaces. Whereas traditional frameworks like React and Vue do the bulk of their work in the browser, Svelte shifts that work into a compile step that happens when you build your app." 184 187 msgstr "Une approche radicale pour la création d'interfaces utilisateur. Alors que les frameworks traditionnels tels que React et Vue effectuent la majeure partie de leur travail dans le navigateur, Svelte déplace ce travail dans une étape de compilation qui se produit lors de la création de l'application." ··· 362 365 msgid "Redirecting you to my github incubator..." 363 366 msgstr "Redirection vers mon incubateur github..." 364 367 365 - msgid "Set of glyphs (letters, punctuation marks and more) that define how text looks." 366 - msgstr "Ensemble de glyphes (lettres, signes de ponctuation et plus encore) qui définissent l'apparence du texte." 367 - 368 368 msgid "School projects and school-related projects" 369 369 msgstr "Projets scolaires et projets liés à l'école" 370 370 371 371 msgid "Server error. I f*cked up somewhere." 372 372 msgstr "Erreur serveur. J'ai foiré quelque part." 373 + 374 + msgid "Set of glyphs (letters, punctuation marks and more) that define how text looks." 375 + msgstr "Ensemble de glyphes (lettres, signes de ponctuation et plus encore) qui définissent l'apparence du texte." 373 376 374 377 msgid "Short introductory video sequences typically played at the beginning of every video" 375 378 msgstr "Séquences vidéo introducientrières courtes qui sont typiquement jouées au début de chaque vidéo"