diff --git a/CHANGELOG.md b/CHANGELOG.md index c7aca9697..cc5c51e85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,12 @@ ## mm/dd/2019 1. [](#new) - * Added new `system.debugger.censored` configuration option to hide potentially sensitive information + * Added new configuration option `system.debugger.censored` to hide potentially sensitive information + * Added new configuration option `system.languages.include_default_lang_file_extension` to keep default language in `.md` files if set to `false` +1. [](#bugfix) + * Fixed `.md` page to be assigned to the default language and to be listed in translated/untranslated page list + * Fixed `Language::getFallbackPageExtensions()` to append `.md` file after the default language extension + * Fixed `Language::getFallbackPageExtensions()` returning wrong file extensions when passing custom page extension # v1.7.0-beta.3 ## 06/24/2019 @@ -46,7 +51,7 @@ * Fixed `url()` returning wrong path if using stream with grav root path in it, eg: `user-data://shop` when Grav is in `/shop` * Fixed `url()` not returning a path to non-existing file (`user-data://shop` => `/user/data/shop`) if it is set to fail gracefully * Fixed `url()` returning false on unknown streams, such as `ftp://domain.com`, they should be treated as external URL - + # v1.6.11 ## 06/21/2019 diff --git a/system/blueprints/config/system.yaml b/system/blueprints/config/system.yaml index 631850c08..c349a9ac6 100644 --- a/system/blueprints/config/system.yaml +++ b/system/blueprints/config/system.yaml @@ -340,6 +340,17 @@ form: validate: type: bool + languages.include_default_lang_file_extension: + type: toggle + label: PLUGIN_ADMIN.INCLUDE_DEFAULT_LANG_FILE_EXTENSION + help: PLUGIN_ADMIN.INCLUDE_DEFAULT_LANG_HELP_FILE_EXTENSION + highlight: 1 + options: + 1: PLUGIN_ADMIN.YES + 0: PLUGIN_ADMIN.NO + validate: + type: bool + languages.pages_fallback_only: type: toggle label: PLUGIN_ADMIN.PAGES_FALLBACK_ONLY diff --git a/system/src/Grav/Common/Language/Language.php b/system/src/Grav/Common/Language/Language.php index a625146a2..3891b443d 100644 --- a/system/src/Grav/Common/Language/Language.php +++ b/system/src/Grav/Common/Language/Language.php @@ -25,7 +25,7 @@ class Language protected $page_extensions = []; protected $fallback_languages = []; protected $default; - protected $active = null; + protected $active; /** @var Config $config */ protected $config; @@ -58,7 +58,7 @@ class Language $this->default = reset($this->languages); } - $this->page_extensions = null; + $this->page_extensions = []; if (empty($this->languages)) { $this->enabled = false; @@ -285,38 +285,50 @@ class Language */ public function getFallbackPageExtensions($file_ext = null) { - if (empty($this->page_extensions)) { + $file_ext = (string)$file_ext; + + if (!isset($this->page_extensions[$file_ext])) { if (!$file_ext) { $file_ext = CONTENT_EXT; } if ($this->enabled()) { + $default = $this->getDefault() ?? 'en'; + $active = $this->getActive() ?? $default; + $valid_lang_extensions = []; - foreach ($this->languages as $lang) { - $valid_lang_extensions[] = '.' . $lang . $file_ext; + + // First add active language. + $valid_lang_extensions[$active] = '.' . $active . $file_ext; + + // If active language is the same as default, count it in, too. + if ($active === $default) { + $valid_lang_extensions[''] = $file_ext; } - if ($this->active) { - $active_extension = '.' . $this->active . $file_ext; - $key = \array_search($active_extension, $valid_lang_extensions, true); - - // Default behavior is to find any language other than active - if ($this->config->get('system.languages.pages_fallback_only')) { - $slice = \array_slice($valid_lang_extensions, 0, $key+1); - $valid_lang_extensions = array_reverse($slice); - } else { - unset($valid_lang_extensions[$key]); - array_unshift($valid_lang_extensions, $active_extension); + if ($this->config->get('system.languages.pages_fallback_only')) { + // Add the extensionless default. + if ($active !== $default) { + $valid_lang_extensions[$default] = '.' . $default . $file_ext; + $valid_lang_extensions[''] = $file_ext; + } + } else { + // We want to have full list of languages. + foreach ($this->languages as $lang) { + $valid_lang_extensions[$lang] = '.' . $lang . $file_ext; + if ($active !== $default) { + $valid_lang_extensions[''] = $file_ext; + } } } - $valid_lang_extensions[] = $file_ext; - $this->page_extensions = $valid_lang_extensions; + + $this->page_extensions[$file_ext] = array_values($valid_lang_extensions); } else { - $this->page_extensions = (array)$file_ext; + $this->page_extensions[$file_ext] = (array)$file_ext; } } - return $this->page_extensions; + return $this->page_extensions[$file_ext]; } /** @@ -332,7 +344,7 @@ class Language */ public function resetFallbackPageExtensions() { - $this->page_extensions = null; + $this->page_extensions = []; } /** @@ -534,4 +546,11 @@ class Language return LanguageCodes::get($code, $type); } + public function __debugInfo() + { + $vars = get_object_vars($this); + unset($vars['grav'], $vars['config']); + + return $vars; + } } diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 2dab3b551..03ca9c543 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -15,6 +15,7 @@ use Grav\Common\Data\Blueprint; use Grav\Common\File\CompiledYamlFile; use Grav\Common\Filesystem\Folder; use Grav\Common\Grav; +use Grav\Common\Language\Language; use Grav\Common\Markdown\Parsedown; use Grav\Common\Markdown\ParsedownExtra; use Grav\Common\Page\Interfaces\PageInterface; @@ -129,7 +130,10 @@ class Page implements PageInterface */ public function init(\SplFileInfo $file, $extension = null) { - $config = Grav::instance()['config']; + $grav = Grav::instance(); + + /** @var Config $config */ + $config = $grav['config']; // some extension logic if (empty($extension)) { @@ -139,8 +143,13 @@ class Page implements PageInterface } // extract page language from page extension - $language = trim(basename($this->extension(), 'md'), '.') ?: null; - $this->language($language); + $languageCode = trim(basename($this->extension(), 'md'), '.') ?: null; + if (!$languageCode) { + /** @var Language $language */ + $language = $grav['language']; + $languageCode = $language->enabled() ? $language->getDefault() : null; + } + $this->language($languageCode); $this->hide_home_route = $config->get('system.home.hide_in_urls', false); $this->home_route = $this->adjustRouteCase($config->get('system.home.alias')); @@ -188,16 +197,32 @@ class Page implements PageInterface */ public function translatedLanguages($onlyPublished = false) { - $filename = substr($this->name, 0, -(strlen($this->extension()))); - $config = Grav::instance()['config']; - $languages = $config->get('system.languages.supported', []); + $grav = Grav::instance(); + + /** @var Language $language */ + $language = $grav['language']; + + $languages = $language->getLanguages(); + $defaultCode = $language->getDefault(); + + $name = substr($this->name, 0, -strlen($this->extension())); $translatedLanguages = []; - foreach ($languages as $language) { - $path = $this->path . DS . $this->folder . DS . $filename . '.' . $language . '.md'; - if (file_exists($path)) { + foreach ($languages as $languageCode) { + $languageExtension = ".{$languageCode}.md"; + $path = $this->path . DS . $this->folder . DS . $name . $languageExtension; + $exists = file_exists($path); + + // Default language may be saved without language file location. + if (!$exists && $languageCode === $defaultCode) { + $languageExtension = '.md'; + $path = $this->path . DS . $this->folder . DS . $name . $languageExtension; + $exists = file_exists($path); + } + + if ($exists) { $aPage = new Page(); - $aPage->init(new \SplFileInfo($path), $language . '.md'); + $aPage->init(new \SplFileInfo($path), $languageExtension); $route = $aPage->header()->routes['default'] ?? $aPage->rawRoute(); if (!$route) { @@ -208,7 +233,7 @@ class Page implements PageInterface continue; } - $translatedLanguages[$language] = $route; + $translatedLanguages[$languageCode] = $route; } } @@ -224,22 +249,41 @@ class Page implements PageInterface */ public function untranslatedLanguages($includeUnpublished = false) { - $filename = substr($this->name, 0, -strlen($this->extension())); - $config = Grav::instance()['config']; - $languages = $config->get('system.languages.supported', []); + $grav = Grav::instance(); + + /** @var Language $language */ + $language = $grav['language']; + + $languages = $language->getLanguages(); + $defaultCode = $language->getDefault(); + + $name = substr($this->name, 0, -strlen($this->extension())); $untranslatedLanguages = []; - foreach ($languages as $language) { - $path = $this->path . DS . $this->folder . DS . $filename . '.' . $language . '.md'; - if (file_exists($path)) { - $aPage = new Page(); - $aPage->init(new \SplFileInfo($path), $language . '.md'); - if ($includeUnpublished && !$aPage->published()) { - $untranslatedLanguages[] = $language; - } - } else { - $untranslatedLanguages[] = $language; + foreach ($languages as $languageCode) { + $path = $this->path . DS . $this->folder . DS . $name . '.' . $languageCode . '.md'; + $exists = file_exists($path); + + // Default language may be saved without language file location. + if (!$exists && $languageCode === $defaultCode) { + $path = $this->path . DS . $this->folder . DS . $name . '.md'; + $exists = file_exists($path); } + + if ($exists) { + if ($includeUnpublished) { + continue; + } + + $aPage = new Page(); + $aPage->init(new \SplFileInfo($path), $languageCode . '.md'); + + if (!$aPage->published()) { + continue; + } + } + + $untranslatedLanguages[] = $languageCode; } return $untranslatedLanguages; @@ -922,13 +966,16 @@ class Page implements PageInterface return $this->slug(); } if ($name === 'name') { + $name = $this->name(); $language = $this->language() ? '.' . $this->language() : ''; - $name_val = str_replace($language . '.md', '', $this->name()); + $pattern = '%(' . preg_quote($language, '%') . ')?\.md$%'; + $name = preg_replace($pattern, '', $name); + if ($this->modular()) { - return 'modular/' . $name_val; + return 'modular/' . $name; } - return $name_val; + return $name; } if ($name === 'media') { return $this->media()->all();