From 41bbaeb9700aab7e98d93801985a6c93886df8db Mon Sep 17 00:00:00 2001 From: GaaH <2855911+GaaH@users.noreply.github.com> Date: Sun, 12 Apr 2020 19:23:17 +0200 Subject: [PATCH] Add an optionnal `lang` parameter to get_url (#982) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * get_url takes an optionnal parameter * Documentation about the 'lang' parameter of 'get_url' Co-authored-by: Gaƫtan Caillaut --- components/templates/src/global_fns/mod.rs | 82 ++++++++++++++++++- .../documentation/templates/overview.md | 10 +++ 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/components/templates/src/global_fns/mod.rs b/components/templates/src/global_fns/mod.rs index dd3b0538..a5a1f7c5 100644 --- a/components/templates/src/global_fns/mod.rs +++ b/components/templates/src/global_fns/mod.rs @@ -53,6 +53,22 @@ impl GetUrl { Self { config, permalinks } } } + +fn make_path_with_lang(path: String, lang: &str, config: &Config) -> Result { + if lang == &config.default_language { + return Ok(path); + } + + if !config.languages.iter().any(|x| x.code == lang) { + return Err(format!("`{}` is not an authorized language (check config.languages).", lang).into()); + } + + let mut splitted_path: Vec = path.split(".").map(String::from).collect(); + let ilast = splitted_path.len() - 1; + splitted_path[ilast] = format!("{}.{}", lang, splitted_path[ilast]); + Ok(splitted_path.join(".")) +} + impl TeraFn for GetUrl { fn call(&self, args: &HashMap) -> Result { let cachebust = @@ -67,11 +83,20 @@ impl TeraFn for GetUrl { args.get("path"), "`get_url` requires a `path` argument with a string value" ); + + let lang = optional_arg!(String, args.get("lang"), "`get_url`: `lang` must be a string.") + .unwrap_or_else(|| self.config.default_language.clone()); + if path.starts_with("@/") { - match resolve_internal_link(&path, &self.permalinks) { + let path_with_lang = match make_path_with_lang(path, &lang, &self.config) { + Ok(x) => x, + Err(e) => return Err(e) + }; + + match resolve_internal_link(&path_with_lang, &self.permalinks) { Ok(resolved) => Ok(to_value(resolved.permalink).unwrap()), Err(_) => { - Err(format!("Could not resolve URL for link `{}` not found.", path).into()) + Err(format!("Could not resolve URL for link `{}` not found.", path_with_lang).into()) } } } else { @@ -516,6 +541,10 @@ mod tests { const TRANS_CONFIG: &str = r#" base_url = "https://remplace-par-ton-url.fr" default_language = "fr" +languages = [ + { code = "fr" }, + { code = "en" }, +] [translations] [translations.fr] @@ -562,4 +591,53 @@ title = "A title" let error = Trans::new(config).call(&args).unwrap_err(); assert_eq!("Failed to retreive term translation", format!("{}", error)); } + + #[test] + fn error_when_language_not_available() { + let config = Config::parse(TRANS_CONFIG).unwrap(); + let static_fn = GetUrl::new(config, HashMap::new()); + let mut args = HashMap::new(); + args.insert("path".to_string(), to_value("@/a_section/a_page.md").unwrap()); + args.insert("lang".to_string(), to_value("it").unwrap()); + let err = static_fn.call(&args).unwrap_err(); + assert_eq!("`it` is not an authorized language (check config.languages).", format!("{}", err)); + } + + #[test] + fn can_get_url_with_default_language() { + let config = Config::parse(TRANS_CONFIG).unwrap(); + let mut permalinks = HashMap::new(); + permalinks.insert( + "a_section/a_page.md".to_string(), + "https://remplace-par-ton-url.fr/a_section/a_page/".to_string() + ); + permalinks.insert( + "a_section/a_page.en.md".to_string(), + "https://remplace-par-ton-url.fr/en/a_section/a_page/".to_string() + ); + let static_fn = GetUrl::new(config, permalinks); + let mut args = HashMap::new(); + args.insert("path".to_string(), to_value("@/a_section/a_page.md").unwrap()); + args.insert("lang".to_string(), to_value("fr").unwrap()); + assert_eq!(static_fn.call(&args).unwrap(), "https://remplace-par-ton-url.fr/a_section/a_page/"); + } + + #[test] + fn can_get_url_with_other_language() { + let config = Config::parse(TRANS_CONFIG).unwrap(); + let mut permalinks = HashMap::new(); + permalinks.insert( + "a_section/a_page.md".to_string(), + "https://remplace-par-ton-url.fr/a_section/a_page/".to_string() + ); + permalinks.insert( + "a_section/a_page.en.md".to_string(), + "https://remplace-par-ton-url.fr/en/a_section/a_page/".to_string() + ); + let static_fn = GetUrl::new(config, permalinks); + let mut args = HashMap::new(); + args.insert("path".to_string(), to_value("@/a_section/a_page.md").unwrap()); + args.insert("lang".to_string(), to_value("en").unwrap()); + assert_eq!(static_fn.call(&args).unwrap(), "https://remplace-par-ton-url.fr/en/a_section/a_page/"); + } } diff --git a/docs/content/documentation/templates/overview.md b/docs/content/documentation/templates/overview.md index ed75db65..1db30acf 100644 --- a/docs/content/documentation/templates/overview.md +++ b/docs/content/documentation/templates/overview.md @@ -117,6 +117,16 @@ link like the ones used in Markdown, starting from the root `content` directory. {% set url = get_url(path="@/blog/_index.md") %} ``` +It accepts an optionnal parameter `lang` in order to compute a *language-aware URL* in multilingual websites. Assuming `config.base_url` is `"http://example.com"`, the following snippet will: + +- return `"http://example.com/blog/"` if `config.default_language` is `"en"` +- return `"http://example.com/en/blog/"` if `config.default_language` is **not** `"en"` and `"en"` appears in `config.languages` +- fail otherwise, with the error message `"'en' is not an authorized language (check config.languages)."` + +```jinja2 +{% set url = get_url(path="@/blog/_index.md", lang="en") %} +``` + This can also be used to get the permalinks for static assets, for example if we want to link to the file that is located at `static/css/app.css`: