Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
Latest 0.2.4. version:
* Support for ISO2 plus ISO 639-1 followed by ISO 3166-1 Alpha 2;
* Better hreflang support; results tested successfully by the flang online tool;
* Now available with two TXP variables: "visitor_lang" and "visitor_iso" for conveniencies;
* New tag added: pat_lang_detect_link for locale sections links creation.
  • Loading branch information
cara-tm committed Jan 6, 2018
1 parent f48ff73 commit 14f45e5
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 128 deletions.
40 changes: 27 additions & 13 deletions README.textile
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ h1. @<txp:pat_lang_detect />@

Textpattern CMS plugin: Simple browser vistor preference language detection for locale redirects and other utilities.

This plugin intents to help for multi languages websites support. Detects the language preference of the visitors browser, then redirect to the corresponding page named by the two matching letters (eg. @en@) if it exists.

*Caution*: This plugin may crashing your pages (your @<head>@ part especially) with Adblock Plus utility. See below how to avoid a such as annoying situation.
This plugin intents to help for multi languages websites support. Detects the language preference of the visitors browser, then can redirect to the corresponding page named by the two matching letters (eg. @en@) if it exists or display a link to the matching section (support default locale section with this other compagnon plugin: pat_text).

h3. Usage

After installation, activate this plugin into your preferences by ticking the "Enable pat_lang_detect?" field. Then, place this tag into your @default@ page template but nothing other else:

* @<txp:pat_lang_detect redirect="1" />@
* @<txp:pat_lang_detect redirect="1" display="0" />@

And... _Voilà!_

Expand Down Expand Up @@ -40,21 +38,30 @@ So, you can overwriting the visitor language in your links by a new one into you

@http://my-website.com/?lang=fr@

h3. TXP variable: @<txp:variable name="visitor_lang" />@
h3. TXP variables: @<txp:variable name="visitor_lang" />@ and @<txp:variable name="visitor_iso" />@

The plugin also creates a TXP variable named @<txp:variable name="visitor_lang" />@ which contains the locale code country (ISO2) of your visitors and available for any conveniences throught your entire website.
The plugin also creates TXP variables named @<txp:variable name="visitor_lang" />@ which contains the locale code country (ISO 639-1 format) of your visitors and available for any conveniences throught your entire website and @<txp:variable name="visitor_iso" />@ which contains language and country codes (ISO 639-1 followed by ISO 3166-1 Alpha 2 formats).

h4. @<txp:pat_lang_default />@

This tag without any attributes returns the current TXP ISO2 active code language set in your interface.

h4. @<txp:pat_lang_compare />@
h3. @<txp:pat_lang_compare />@

A simple comparaison tag between the TXP default language and the visitor one. Can be use into breadcrumb links to redirect to the home page version translated into the visitor language.

h3. @<txp:pat_lang_detect_link />@

This tag can create an HTML link to locale sections.

A simple comparaison tag between the TXP default language and the visitor one. Can be use into breadcrumb links to redirect to the home page version translated into the visitor language.
h4. Attributes

h4. Usage for Adblocks Plus
* @label@ (string) required: the text for the link. Default: empty.
* @section@ (string) required: the section name. Default: empty.

We noticed the Adblock Plus tool hides the @<head>@ part of a page document if @&lt;txp:pat_lang_detect /&gt;@ tag is present in it (especially within the @<html>@ tag).
h3. Usage for Adblocks Plus

We noticed the Adblock Plus tool sometimes hides the @<head>@ part of a page document if @&lt;txp:pat_lang_detect /&gt;@ tag is present in it (especially within the @<html>@ tag).
To avoid all problems, here is how to check and retrieve the ISO2 code into the @lang@ attribute:

bq. &lt;html lang="&lt;txp:if_section name=""&gt;&lt;txp:lang /&gt;&lt;txp:else /&gt;&lt;txp:pat_lang_detect /&gt;&lt;txp:variable name="visitor_lang" /&gt;&lt;/txp:if_section&gt;" dir="&lt;txp:text item="lang_dir" /&gt;"&gt;
Expand All @@ -79,15 +86,19 @@ p{width:100%;text-align:right;font-size:small}. _Above: A french website sample_
h3. @<txp:pat_lang_meta_href />@

This tag, without any attributes, is dedicated to your @<head>@ document part in order to add the alternate links to each locale pages of your website. This practice intents to get good spots for your SEO efforts.
This plugin *works only* within @section@ into the permlinks preference choice of your website (i.e.: @section/id/title@ or @section/title@ permlinks format).
This plugin *works only* within @section@ into the permlinks preference choice of your website (i.e.: @section/id/title@ or @section/title@ permlinks format).

You will need to create your locale sections (i.e. @en@ or @en-us@) and attach them to your @default@ page template.

Note: This plugin can identify section names with only 2 letters and/or with 2 letters followed by an hyphen and 2 other letters.

h4. Usage

Place this tag into the @<head>@ part of your HTML document:

bq. &lt;txp:pat_lang_meta_href /&gt;

This tag checks all your locale sections available (named by 2 letters in ISO2 format) and injects all alternate links accordingly, e.g. (this case for an english site):
This tag checks all your locale sections available (named by 2 letters in ISO2 format and/or 4 letters with an hyphen separator) and injects all alternate links accordingly, e.g. (this case for an english site):

bq. &lt;link rel="alternate" hreflang="x-default" href="http&#8202;://example.com/"&gt;
&lt;link rel="alternate" hreflang="de" href="http&#8202;://example.com/de"&gt;
Expand All @@ -97,14 +108,17 @@ bq. &lt;link rel="alternate" hreflang="x-default" href="http&#8202;://example.co
Note: @x-default@ value if a *default section* is found same as the website default @active language@ sets in the languages preferences.
Alternative links are displayed in default order as populated into the 'section' table; individual alternative links are displayed in the order of the corresponding article #IDs.

Tested successfully with the online "http://flang.dejanseo.com.au/":http://flang.dejanseo.com.au/ tool.

h2. Custom field: @<txp:custom_field name="Twin_ID" />@

For individual alternate href links, use a custom field named @Twin_ID@ to store a comma separated list of IDs of the corresponding translated articles (the current locale one, included). The alternate links will be generated automaticaly in an individual article context.
For individual alternate href links, use a custom field named @Twin_ID@ to store a comma separated list of IDs of the corresponding translated articles (the current locale one, included). The alternate @hreflang@ links will be generated automaticaly in an individual article context.

h3. Histoy and Changelog

Plugin created for the "FOTO" prenium TXP theme.

* 24 ^th^ December 2017. v 0.2.4.
* 23 ^rd^ December 2017. v 0.2.3.
* 13 ^th^ December 2017. v 0.2.1 & 0.2.2.
* 6 ^th^ December 2017. v 0.2.
Expand Down
120 changes: 66 additions & 54 deletions pat_lang_detect.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* @type: Public
* @prefs: no
* @order: 5
* @version: 0.2.3
* @version: 0.2.4
* @license: GPLv2
*/

Expand All @@ -19,7 +19,8 @@
->register('pat_lang_detect')
->register('pat_lang_default')
->register('pat_lang_meta_href')
->register('pat_lang_compare');
->register('pat_lang_compare')
->register('pat_lang_detect_link');
}


Expand All @@ -38,7 +39,7 @@
* Part of this code based on Robert Wetzlmayr's script.
*
* @param $atts array This plugin attributes
* @return string ISO2 language code
* @return string Redirect or link
*/
function pat_lang_detect($atts)
{
Expand All @@ -49,87 +50,68 @@ function pat_lang_detect($atts)
'display' => false,
), $atts));

_pat_lang_detect_start_session();

$langs = explode(',', @$_SERVER["HTTP_ACCEPT_LANGUAGE"]);
$_SESSION['language'] = preg_replace('/(?:(?<=([a-z]{2}))).*/', '', $langs[0]);

// Create a 'visitor_lang' variable for conveniences, default: prefs lang.
if (!empty($_SESSION['language']) && false != $prefs['pat_lang_detect_enable'])
$variable['visitor_lang'] = $_SESSION['language'];
else
$prefs['pat_lang_detect_enable'] ? $variable['visitor_lang'] = substr(get_pref('language'), 0, 2) : '';
if (false != $prefs['pat_lang_detect_enable']) {
$variable['visitor_iso'] = strtolower($langs[0]);
$variable['visitor_lang'] = preg_replace('/(?:(?<=([a-z]{2}))).*/', '', $langs[0]);
} else {
$variable['visitor_lang'] = $prefs['pat_lang_detect_enable'] ? substr(get_pref('language'), 0, 2) : '';
}

// Change 'visitor_lang' variable by the $_GET value from URLs
if (gps('lang'))
$variable['visitor_lang'] = gps('lang');

// Overwrite 'visitor_lang' variable within a 2 letters section name (ISO2 code)
if (strlen($pretext['s']) == 2)
$variable['visitor_lang'] = $pretext['s'];
// Overwrite variables within a locale section name (ISO code)
if (preg_match('/^[a-z]{2}(\-[a-zA-Z]{2})?$/', $pretext['s'])) {
$variable['visitor_lang'] = substr($pretext['s'], 0, 2);
$variable['visitor_iso'] = $pretext['s'];
}

// Redirection to locale page or not; otherwise display only the URL
if ($variable['visitor_lang'] != substr(get_pref('language'), 0, 2)) {
if ($variable['visitor_iso'] != get_pref('language')) {
if (true != $redirect)
return $display ? hu._pat_lang_detect_section_name($variable['visitor_lang']) : '';
return $display ? hu._pat_lang_detect_section_name($variable['visitor_iso']) : '';
else
header('Location: '.hu._pat_lang_detect_section_name($variable['visitor_lang']));
header('Location: '.hu._pat_lang_detect_section_name($variable['visitor_iso']));
}

}


/**
* Session function
*
* @param
* @return boolean
*/
function _pat_lang_detect_start_session()
{
if (headers_sent()) {
if (!isset($_SESSION)) {
$_SESSION = array();
}
return false;
} elseif (!isset($_SESSION)) {
session_cache_limiter("must-revalidate");
session_start();
return true;
} else {
return true;
}
}


/**
* A simple helper tag to get the ISO2 code of the default TXP language
* A simple helper tag to get the ISO code of the default TXP language
*
* @param
* @return string ISO2 code
*/
function pat_lang_default()
{

return substr(get_pref('language'), 0, 2);
}


/**
* Compares a variable from names stored into the 'section' table
*
* @param $code string ISO2 language code
* @return $code string ISO2 language code found in DB
* @param $code string ISO language code
* @return $code string ISO language code found in DB
*/
function _pat_lang_detect_section_name($code)
{
global $DB;
$DB = new DB;
$rs = safe_field('name', 'txp_section', "name = '".doSlash($code)."'");

$out = false;

if (preg_match('/^[a-z]{2}(\-[a-zA-Z]{2})?$/', $code))
$rs = safe_field('name', 'txp_section', "name = '".doSlash($code)."'");

if ($rs)
$out = $code;
else
$out = '';

return $out;
}
Expand All @@ -146,23 +128,23 @@ function pat_lang_meta_href()
global $pretext, $is_article_list;
$out = '';

// ISO2 lang prefs
$current = pat_lang_default();
// ISO lang prefs
$current = get_pref('language');
// Loads main function
pat_lang_detect(array('redirect' => 0, 'display' => 0));
// Query: get all section names
$data = safe_rows('name', 'txp_section', "1=1");
$data = safe_rows('name', 'txp_section', "1=1 AND CHAR_LENGTH(name) < 6");

if ($pretext['s'] == 'default' || (strlen($pretext['s']) == 2 && true == $is_article_list)) {
if ($pretext['s'] == 'default' or (false != _pat_lang_detect_section_name($pretext['s']) and true == $is_article_list)) {
$out .= '<link rel="alternate" hreflang="x-default" href="'.hu.'">'.n;
// Loop for locale sections
foreach ($data as $value) {
if (strlen($value['name']) == 2 && $value['name'] != $current)
if (preg_match('/^[a-z]{2}(\-[a-zA-Z]{2})?$/', $value['name']) && $value['name'] != $current)
$out .= '<link rel="alternate" hreflang="'.$value['name'].'" href="'.pagelinkurl(array('s' => $value['name'])).'">'.n;
}
} else {
// Is there a 'Twin_ID' custom_field for this individual article?
if (custom_field(array('name' => 'Twin_ID')) && custom_field(array('name' => 'Twin_ID')) != article_id(array())) {
if (custom_field(array('name' => 'Twin_ID')) and custom_field(array('name' => 'Twin_ID')) != article_id(array())) {
// Check all in the comma separated list of IDs
$list = explode(',', trim(custom_field(array('name' => 'Twin_ID'))));
foreach($list as $id) {
Expand All @@ -185,9 +167,9 @@ function _pat_lang_detect_section_grab($scheme)
{

if ($scheme)
preg_match('%\/([a-z]{2})\/%', $scheme, $m);
preg_match('%\/([a-z]{2})(\-[a-zA-Z]{2})?\/%', $scheme, $m);

if ($m[1] == substr(get_pref('language'), 0, 2))
if ($m[1] == get_pref('language'))
$ref = 'x-default';
else
$ref = $m[1];
Expand Down Expand Up @@ -215,6 +197,37 @@ function pat_lang_compare()
}


/**
* Generate a link to locale sections
*
* @param $label string The label of the link
* @param $section string The section (ISO code)
* @return string HTML link
*/
function pat_lang_detect_link($atts)
{

global $variable;

extract(lAtts(array(
'label' => false,
'section' => false,
), $atts));

if ($label && $section) {
if ($variable['visitor_lang'] !== pat_lang_default())
$out = '<p><span><a href="'.hu.$section.'">'.$label.'</a></span></p>';
else
$out = '';
} else {
$out = '';
}

return $out;

}


/**
* This plugin preferences
*
Expand Down Expand Up @@ -244,4 +257,3 @@ function pat_lang_detect_cleanup()
{
safe_delete('txp_prefs', "name='pat_lang_detect_enable'");
}

61 changes: 0 additions & 61 deletions pat_lang_detect_v0.2.3_zip.txt

This file was deleted.

Loading

0 comments on commit 14f45e5

Please sign in to comment.