Add an optionnal lang parameter to get_url (#982)

* get_url takes an optionnal  parameter

* Documentation about the 'lang' parameter of 'get_url'

Co-authored-by: Gaëtan Caillaut <gaetan.caillaut@live.com>
This commit is contained in:
GaaH 2020-04-12 19:23:17 +02:00 committed by GitHub
parent b2eb00a374
commit 41bbaeb970
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 90 additions and 2 deletions

View file

@ -53,6 +53,22 @@ impl GetUrl {
Self { config, permalinks } Self { config, permalinks }
} }
} }
fn make_path_with_lang(path: String, lang: &str, config: &Config) -> Result<String> {
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<String> = 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 { impl TeraFn for GetUrl {
fn call(&self, args: &HashMap<String, Value>) -> Result<Value> { fn call(&self, args: &HashMap<String, Value>) -> Result<Value> {
let cachebust = let cachebust =
@ -67,11 +83,20 @@ impl TeraFn for GetUrl {
args.get("path"), args.get("path"),
"`get_url` requires a `path` argument with a string value" "`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("@/") { 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()), Ok(resolved) => Ok(to_value(resolved.permalink).unwrap()),
Err(_) => { 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 { } else {
@ -516,6 +541,10 @@ mod tests {
const TRANS_CONFIG: &str = r#" const TRANS_CONFIG: &str = r#"
base_url = "https://remplace-par-ton-url.fr" base_url = "https://remplace-par-ton-url.fr"
default_language = "fr" default_language = "fr"
languages = [
{ code = "fr" },
{ code = "en" },
]
[translations] [translations]
[translations.fr] [translations.fr]
@ -562,4 +591,53 @@ title = "A title"
let error = Trans::new(config).call(&args).unwrap_err(); let error = Trans::new(config).call(&args).unwrap_err();
assert_eq!("Failed to retreive term translation", format!("{}", error)); 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/");
}
} }

View file

@ -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") %} {% 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 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`: we want to link to the file that is located at `static/css/app.css`: