=== Datoden Language Switcher ===
Contributors: datoden
Tags: multilingual, translation, language switcher, languages, hreflang
Requires at least: 6.5
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 3.0.16
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Your website in two languages – the second language on its own address (/en/), with linked pages and a language switcher in the menu.

== Description ==

In the WordPress admin the plugin is shown as "DT-language" in the DT-addons menu (Datoden's menu).

DT-language puts your website in two languages: the main language on the website's usual address and one more language on its own address on the same domain (for example /en/).

* Two languages: the main language and a second language with its own address on the same domain (/en/).
* Pages are linked to their translations. Click + EN next to a page in the page list: a copy opens, ready to be translated.
* The page and post lists show the language of every page, can be filtered by language and show a page and its translations in consecutive rows.
* The start page, the sections on it, the contact page, the privacy page and placed DT-slideshow slideshows follow the language automatically.
* Menus follow the language: pages in the menu go to their translations.
* Language switcher (SV / EN) last in the menu, where the theme puts it, or the shortcode [datoden_language_switcher].
* hreflang links for search engines, the right language in <html lang> and WordPress' own texts in the visitor's language.
* A page opened on the wrong language address is redirected to the right one.
* DT-contact forms are shown in the visitor's language, and their texts are written per language in DT-contact.
* No extra tables, nothing loaded from other servers.

= For themes and plugins =

* apply_filters('datoden_lang_id', $page_id) gives the page in the visitor's language.
* do_action('datoden_language_switcher') prints the language switcher where the theme wants it (with add_theme_support('dt-language-switcher')).
* Filters for own addresses per language (datoden_lang_path), language-neutral pages shown in both languages (datoden_lang_neutral_post), own hreflang addresses (datoden_lang_alternates) and translation of whole pages with a dictionary (datoden_lang_dictionary, datoden_lang_translate_output, datoden_lang_output).
* REST: POST /wp-json/datoden-language/v1/translation creates or updates a translation (for editors who may edit the page).

= Pro add-on =

In the separate paid add-on Datoden Language Switcher Pro (from Datoden, not on WordPress.org): more than two languages, an own domain per language, an own menu per language, translation of the theme's texts, the site title and the menu labels in Customize, translation of the slideshows' texts in DT-slideshow, and changing any text directly on the website. DT-language works fully without it.

== External services ==

This plugin can connect to Datoden (https://datoden.com), a service run by Responsit AB, Sweden. The connection is optional – everything in the plugin works without it. Nothing is sent to Datoden until an administrator clicks "Start DT-website-guard" (or "Connect") in the WordPress admin and approves the connection on datoden.se or datoden.com. You can disconnect at any time with "Disconnect" (or by turning DT-website-guard off) on the DT-website-guard page; then nothing more is sent.

What is sent to Datoden, and when (only while the website is connected, except the connection itself):

* When you connect: the website address, the administrator's language (Swedish or English), the WordPress address that Datoden returns to and a random check value. After you approve on Datoden, the website sends the one-time code it got back, together with the website address and the language, and receives a website key that is stored in your database.
* Once a day (WordPress cron), and when an administrator opens a DT plugin page and the last contact is more than six hours old: the website key, the language, and the folder names, versions and active state of the installed Datoden plugins (for example datoden-cookie-consent). The answer can contain short messages from Datoden and updated wording for the DT plugins' texts, which are shown on the plugins' pages.
* When an administrator opens the DT-website-guard page or a DT plugin page (at most every five minutes), or clicks "Check again": the website key, to get the latest result of Datoden's monitoring (up or down, response time, and the expiry dates of the SSL certificate and the domain). "Check again" also asks Datoden to check the website once more.
* When the DT-website-guard page is shown and the DT-website-guard plugin is installed: the list of Datoden's plugins and their versions is fetched from datoden.se, at most every six hours. No data about the website is sent.
* When you click "My websites": the website key, the language and the email address of the logged-in WordPress user, so that Datoden can sign you in directly if it is the same address as your Datoden account.
* When you save, use or delete a settings profile: the website key, and when saving the settings of DT-cookie and DT-darkmode (no personal data; website-specific values such as the logo and the privacy page are left out). They are stored in or read from your Datoden account.
* When you disconnect: the website key, so that Datoden can remove it.
* While connected, Datoden visits the public website every five minutes (like any visitor) to check that it is up, reads its SSL certificate and looks up the domain's public registration data to find when it expires. The plugin shows the dates as Datoden reports them; the website does not contact any other service for this.

Datoden terms: https://datoden.com/terms/
Datoden privacy policy: https://datoden.com/privacy-policy/

== Source code ==

Everything in this plugin is the original, human-readable source code. The PHP, JavaScript and CSS files are written by hand and are neither minified nor generated by a build tool, so there is no build step: the files in the plugin folder are the source and can be read and edited directly.

== Changelog ==

= 3.0.16 =
Core 3.0.8: the return from Datoden (Connect) is also checked with a WordPress nonce (WordPress.org review); the readme describes the source code.

= 3.0.15 =
The admin bar icon is always the DT-language logo; the chosen language (SV, EN …) is a small badge to the right of the name, hidden on screens with nothing to translate.

= 3.0.14 =
On screens with nothing to translate, the admin bar icon shows the DT-language icon instead of the last chosen language (greyed out).

= 3.0.13 =
The language you edit texts in is a menu in the admin bar next to DT-cache: the icon shows the chosen language (SV, EN …) and the menu has the languages and Text fields. The menu is on every wp-admin screen, including Datoden's own (the choice used to move up into their header), and applies on screens that register, under Appearance → Menus and on every screen with fields that can be written per language – otherwise greyed out with an explanation.

= 3.0.12 =
Faster pages in languages other than the main one: theme settings holding numbers (e.g. sizes) are checked with one query per page view – previously one query for every number each time the settings were read (several hundred queries per page).

= 3.0.11 =
Faster pages: a page's translations (the pages and their languages) are loaded with one query instead of two per translation.

= 3.0.10 =
Datoden-core 3.0.7: the plugins' settings are checked with a single database query when the page loads – missing or non-autoloaded settings used to cost one query each on every page.

= 3.0.9 =
* Review fixes in all plugins: prefixed JavaScript names, the WordPress 6.9 template enhancement output buffer (older WordPress: the buffer is closed explicitly), cache paths from content_url(). Dark Mode: block theme palettes are converted per use. SVG Support: steps back while the SVG Support plugin is active. Code Snippets: the WPCode switch button is shown for all imported snippets.

= 3.0.8 =
* Datoden-core 3.0.5: the plugin icon shows its symbol at full size, cut by the corner with the Datoden logo.

= 3.0.7 =
* Datoden-core 3.0.4: plugin icons without the white background – the cut corner is transparent and the Datoden logo uses the icon's light colour.

= 3.0.6 =
* Datoden-core 3.0.3: new plugin icon design – a cut white corner with the Datoden logo.

= 3.0.5 =
* Datoden-core 3.0.2: the plugin's own icon (the same as on WordPress.org) is shown in the DT-addons overview and in the header of the plugin's page.

= 3.0.4 =
* Datoden-core 3.0.1: the header on the plugin's page shows the plugin's name as on WordPress.org.

= 3.0.3 =
* Fix: since the rename, DT-language loads before plugins that control the languages. The language is now decided again once all plugins have loaded, so a language on its own domain gets that domain's address again.

= 3.0.2 =
* After changing the main language the page list shows + for the new main language on pages that only exist in the old one (it was missing), and a translation is listed under its original whatever the language. The Language box shows Translation of also for pages in the main language.

= 3.0.1 =
* Change the main language: the button Make main language moves a language to the website's usual address and gives the old main language its own address (for example /sv/). Pages, the front page, the menus, the theme's page choices and slideshow placements follow, and old addresses are redirected (301). The main language's code can be corrected. The main language's WordPress language now also applies on the website. The page cache is cleared when the languages change.

= 3.0.0 =
* New name on WordPress.org: Datoden Language Switcher (shown as DT-language in the DT-addons menu). The free plugin contains no locked Pro features – they are only in the separate Datoden Language Switcher Pro. Websites with the earlier version are moved to the new folder automatically; settings are kept.

= 2.0.1 =
* Plugin Check: redirects to Datoden use wp_safe_redirect, and the descriptions on the Datoden plugins overview are translated with WordPress' own function. Datoden-core 2.0.1.

= 2.0.0 =
* New prefix datoden_ instead of dt_ (WordPress.org). Settings and data are moved automatically on the first load; the old [dt_…] shortcodes, hooks and REST routes keep working. Works together with older DT plugins until they are updated. Datoden-core 2.0.0.

= 1.6.12 =
* Ready for WordPress.org: Plugin Check rules (sanitising, nonces, WordPress file functions), no inline scripts in admin pages, DT-core 1.17.22.

= 1.6.11 =
* DT-core 1.17.21: shared core cleaned up (unused code removed) – the same core in every plugin, no change in behaviour.

= 1.6.10 =
* Cleanup: unused code removed – no change in behaviour.

= 1.6.9 =
* The Pro card mentions editing texts directly on the website (click and type). DT-core 1.17.20.

= 1.6.8 =
* DT-core 1.17.12: the menu heading is called DT-addons and the overview section Datoden plugins.

= 1.6.7 =
* DT-core 1.17.11: the Pro features require a licence – the website must be connected to Datoden and have a purchased licence or be activated by Datoden. Without a licence the base plugin runs without Pro, with a notice saying why (three days to connect after installing or updating).

= 1.6.6 =
* DT-core 1.17.10: DT-website-guard includes itself in the list sent to Datoden – Control the website, Health and Updates show again in My websites, and DT-website-guard gets its updates from Datoden.

= 1.6.5 =
* DT-core 1.17.9: the menu heading is called Datoden Addons (DT-datoden-addons wrapped onto two lines).

= 1.6.4 =
* DT-core 1.17.8: the menu heading is called DT-datoden-addons (without the Pro badge); the first row in the menu and the overview are still called DT-website-guard.

= 1.6.3 =
* DT-core 1.17.7: the DT-website-guard overview shows every DT plugin – the ones that are not installed with Install (downloaded from Datoden) and Read more; deactivated ones with Activate.

= 1.6.2 =
* DT-addons is now called DT-website-guard (the menu, the overview, the plugins list and the texts in every DT plugin). The folder and the settings stay the same (dt-addons), so updates and everything saved work as before. DT-core 1.17.6.

= 1.6.1 =
* DT-core 1.17.5: the card about what Pro adds is shown at the top of the sidebar (only without Pro) – in every DT plugin.

= 1.6.0 =
* For themes and plugins: more than one domain for a language (aliases), own addresses per language (filter dt_lang_path), language-neutral pages shown in every language (dt_lang_neutral_post), own hreflang addresses (dt_lang_alternates) and translation of whole pages with a dictionary (dt_lang_dictionary, dt_lang_translate_output, dt_lang_output). Nothing changes for websites that don't use the hooks.

= 1.5.4 =
* No Filter button in the page and post lists: date, category and language filter as soon as they are chosen.

= 1.5.3 =
* New "Translations together" button above the page and post lists turns grouping on and off (saved per user, on by default). When on, translations stay in consecutive rows also when sorting by Title, Date or other columns and when searching – groups are sorted by the original's value in the chosen direction.

= 1.5.2 =
* Page and post lists are grouped: a page and its translations appear in consecutive rows (original first, translations below with a small arrow). Groups keep WordPress's usual order – pages by order and title, posts by date – using the original's values. Clicking a column header, searching or choosing a language sorts as usual.

= 1.5.1 =
* Clear which language a page belongs to: in the Language column the page's own language is a filled tag with a check mark, the other languages are outlined links (pencil = exists, + = create). The Language box in the editor shows the page's language at the top (code and name), then the page it translates and Other languages. Also in dark mode.

= 1.5.0 =
* Free and Pro in one: Pro is now an add-on to DT-language instead of a separate version that replaces it. DT-language (the base plugin, free on WordPress.org) stays installed and active, keeps the settings and is updated from there; DT-language Pro adds the Pro features and requires DT-language. Upgrade, go back or remove Pro – settings and data stay. If DT-language is newer than Pro, DT-language runs without the Pro features until Pro has been updated. DT-core 1.17.0.

= 1.4.1 =
* Fix: critical error when DT-language Pro was installed while an older free version was active. Pro now turns the free version off immediately and starts from the next request.

= 1.4.0 =
* Free and Pro: built as a free version (WordPress.org) and DT-language Pro (Datoden). Pro takes over the free version and keeps the settings, is updated from Datoden while connected and shows Pro in the header. Nothing stops working when switching either way. DT-core 1.16.0.

= 1.3.31 =
* DT-core 1.15.1: the header (logo, Datoden badge, buttons, language switch, Saved) and the Made by Datoden line are rendered by the core – the plugin only provides its name, version, description and any tabs. The collapse/expand arrow always sits at the far right of the card.

= 1.3.30 =
* DT-core 1.14.0: the header, the DT-addons menu and everything else shared (dt-hub.php, dt-autosave.js, dt-admin.css and Datoden images) live in the dt-core/ folder. Of all active DT plugins only the newest copy is used – updating one plugin with a newer core gives every plugin the new header, and all pages load the same files (cached once by the browser).

= 1.3.29 =
* Shared header script: in DT-addons, Messages go below Install or update in the sidebar.

= 1.3.28 =
* The tab row sits at the top of the main column – above the main cards only, so the sidebar starts at the top beside it.

= 1.3.27 =
* Tabs (e.g. Languages | Menus in DT-language) are a full-width row right below the header, above the cards – no longer small inside the header, so they are not missed.

= 1.3.26 =
* Every card – also in the main column and the cards above it – collapses and expands with a click on its heading. The arrow sits right after the heading, so switches and buttons on the right stay visible when the card is collapsed.

= 1.3.25 =
* Sidebar cards collapse and expand with a click on their heading – remembered per card. Collapsed Messages shows the count. In DT-addons the Datoden account is at the top of the sidebar (DT-hub 1.13.2).

= 1.3.24 =
* Languages page redesigned: each language is its own card with name, code and WordPress language; the address is a clear choice (address on this domain or own domain) with a live preview. New languages are added with + Add language and saved when you leave the card. Tidier switcher and menu settings.

= 1.3.23 =
* Closed messages stay closed after reloading the page.

= 1.3.22 =
* Messages are shown in the sidebar (Messages card) instead of the header.

= 1.3.21 =
* The first item under DT-addons in the menu is called DT-addons instead of Overview.

= 1.3.20 =
* The Datoden menu is now called DT-addons; the overview has a larger DT-website-guard panel.

= 1.3.19 =
* Undo/Redo tooltips say what will be undone or redone. Undo, Redo and Saved are always in the same place, greyed out when there is nothing to do.

= 1.3.18 =
* Header: subtle dividers between the groups of controls.

= 1.3.17 =
* Undo now works everywhere, also right after a change, for added/removed rows, the form builder and the code editor.

= 1.3.16 =
* Undo / Redo in the header of every DT plugin. The save status keeps its width; other messages are shown on top so nothing moves.

= 1.3.15 =
* Header rearranged: version next to the plugin name, buttons top right, Saved after the language switch, the Datoden logo links to Datoden's apps.

= 1.3.14 =
* The Datoden overview page has the same header as the plugins.

= 1.3.13 =
* Dark mode: the header shows the light Datoden logo (datoden-logo-darkmode.svg).

= 1.3.12 =
* The sidebar toggle moved into the header; when hidden the content uses the full width. The collapsed header shows the Datoden logo.

= 1.3.11 =
* The Languages and Menus tabs moved into the header, so the content is not pushed down.

= 1.3.10 =
* The sidebar toggle sits in the top right corner with a sidebar icon.

= 1.3.9 =
* Header buttons: keep the header at the top while scrolling (pin) and collapse it so only Saved and the language switch show. The sidebar can be collapsed to a small button. The language switch is greyed out on pages without texts to translate.

= 1.3.8 =
* Shared stylesheet updated, same as the other DT plugins.

= 1.3.7 =
* The plugin header now stays at the top when you scroll. Saved status and the SV | EN language switch moved from the admin bar into the header, below the badges.

= 1.3.6 =
* Unified names: the plugin is now called DT-language - datoden (lowercase after DT, like all DT plugins). The folder, settings and shortcodes are unchanged.

= 1.3.5 =
* Page cache: with DT-cache (which saves pages per domain) the front page and the language domains are cached too. The cache block now only applies when a page cache without domains (for example WP Fastest Cache) is active.

= 1.3.4 =
* Text fields is now an on/off switch instead of a checkbox – in the admin bar and in the Customizer. The language switch and Saved no longer get a different background on hover.

= 1.3.3 =
* Saved / Saving… is shown in the admin bar at the top, to the left of the SV | EN language switch (also on mobile) – no longer in the plugin's page header.

= 1.3.2 =
* Messages in the page header: WordPress and plugin notices, messages from Datoden and the Datoden account row (DT-website-guard, Datoden apps) now sit in the page header, to the left of Saved, instead of pushing the page down. Long messages show two lines – click for the full text.

= 1.3.1 =
* Autosave: the settings are saved as soon as something changes – the Save button is removed. The status (Saved / Saving… / Could not save) is shown in the page header, as in DT-slideshow. Adding or removing a language reloads the page after saving.

= 1.3.0 =
* Text fields: a checkbox next to the SV | EN switch (in the admin bar and in Customize) highlights every field on the page with text you can write for the chosen language. Saved per user.

= 1.2.1 =
* The SV | EN switch in the admin bar is also shown in DT-cookie (1.6.0), which follows DT-language's languages.

= 1.2.0 =
* One shared language switch for editing, always in the same place: SV | EN in the admin bar in DT-slideshow and DT-contact, and in the Customize header next to Publish. The choice is the same everywhere and saved per user.

= 1.1.1 =
* DT-contact: the forms' texts are translated directly with the forms (language switch at the top, requires DT-contact 1.7.0), and visitors see the form in their language.

= 1.1.0 =
* Translations live where the texts are. A language switch at the top of Appearance → Customize shows every translatable field in the chosen language (with the main language as a hint) and previews the site in that language; shared fields (images, colours, choices) are marked All languages.
* Menu labels are translated in Customize → Menus, and slideshow texts directly in the DT-slideshow builder (language switch at the top, requires DT-slideshow 3.29.0). Existing piece-by-piece slideshow translations are moved there once.
* Languages follow the settings: adding or removing a language updates everything at once. The Texts tab is removed; all existing translations are kept.
* Themes can choose fields with the dt_lang_customizer_controls filter (for example the Responsit footer and hero buttons).

= 1.0.8 =
* Texts: themes and plugins can add their own keys for translation (for example the Responsit footer), and formatted texts (bold, italic, links, images) keep their formatting when saved.

= 1.0.7 =
* Page cache: WP Fastest Cache ignores DONOTCACHEPAGE, so pages that must not be cached (the other domain, the front page) now also carry its own [wpfcNOT] marker in a hidden HTML comment. The page cache is cleared once after updating.

= 1.0.6 =
* Own domain and page cache: the other domain is never cached – the block is now set as soon as the plugin loads, so page caches such as WP Fastest Cache see it in time.
* The front page and other addresses that are the same on both domains are not cached on the default domain either (page caches store per path, not per domain).
* The page cache is cleared once after updating.

= 1.0.5 =
* Own domain: www.example.com redirects to the domain as it is set (example.com), so search engines see one address.

= 1.0.4 =
* The language list opens upwards when there is no room below the button (for example a menu at the bottom of the screen).

= 1.0.3 =
* Language switcher as a small drop-down: a globe and the language code, the languages drop down on hover, click or keyboard.
* Place it where the theme puts it (do_action('dt_language_switcher'), add_theme_support('dt-language-switcher')) or last in a menu.

= 1.0.2 =
* Slideshows: slide texts, buttons and slideshow names from DT-slideshow (3.27.21 or later) are translated under Texts – each piece of text once, for all slides.

= 1.0.1 =
* Published translations are no longer added to the main language's menus (Automatically add new top-level pages).
* Themes can list their own texts, also default texts, with the filter dt_lang_string_sources.

= 1.0.0 =
* First version.

== Upgrade Notice ==

= 2.0.0 =
Install all DT plugins together; settings are moved automatically.
