How to render style according to the url parameter? - asp.net-mvc

I need to replace css file according to url parameter, site and site/index/en need to get different style.
so how can i do something like this:
#section css {
#Styles.Render(#RouteData.Values["id"] == "en" ? "~/Content/holdings/en" : "~/Content/holdings" )
}

That is pretty close, I think you're just missing the ViewContext;
#section css {
#Styles.Render(ViewContext.RouteData.Values["id"].ToString() == "en" ? "~/Content/holdings/en" : "~/Content/holdings" )
}

I've had a similar case where i had to switch between languages and i used cookies to store the users chosen language
so you could use something similar to this
#{
var lang = "~/Content/holdings/";
lang += Request.Cookies["key"].Value; //they key will hold they lang Code in this case en
#Styles.Render(lang)
}
keep in mind if you dont want to use a cookie you can use a session as well
if you have many different CSS file then store the filepaths in an array and then looping the arraylist adding en to the string.
I hope this answer helps you out.
PS I would recommend a class that is specifically built for this validating the incoming parameter from the URL if you wish to continue and implement a fallback language in case something goes wrong so that the page will also render correctly.

Related

TYPO3 - Retrieved TypoScript in itemsProcFunc are incomplete

I have following problem:
We are overriding the tt_content TCA with a custom column which has an itemsProcFunc in it's config. In the function we try to retrieve the TypoScript-Settings, so we can display the items dynamically. The problem is: In the function we don't receive all the TypoScript-Settings, which are included but only some.
'itemsProcFunc' => 'Vendor\Ext\Backend\Hooks\TcaHook->addFields',
class TcaHook
{
public function addFields($config){
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
$configurationManager = $objectManager->get('TYPO3\\CMS\\Extbase\\Configuration\\ConfigurationManagerInterface');
$setup = $configurationManager->getConfiguration(
\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT
);
}
$setup is now incomplete and doesn't contain the full TypoScript, for example some of the static-included TypoScript is missing.
Used TYPO3 7 LTS (7.6.18), PHP 7.0.* in composer-mode.
Does anybody know where the problem is? Is there some alternative?
You maybe misunderstood the purpose of TypoScipt. It is a way of configuration for the Frontend. The Hook you mentioned is used in the TCA, whích is a Backend part of TYPO3. TypoScript usually isn't used for backend related stuff at all, because it is bound to a specific page template record. Instead in the backend, there is the TSConfig, that can be bound to a page, but also can be added globally. Another thing you are doing wrong is the use of the ObjectManager and the ConfigurationManager, which are classes of extbase, which isn't initialized in the backend. I would recommend to not use extbase in TCA, because the TCA is cached and loaded for every page request. Instead use TSConfig or give your configuration settings directly to the TCA. Do not initialize extbase and do not use extbase classes in these hooks.
Depending on what you want to configure via TypoScript, you may want to do something like this:
'config' => [
'type' => 'select',
'renderType' => 'singleSelect',
'items' => [
['EXT:my_ext/Resources/Private/Language/locallang_db.xlf:myfield.I.0', '']
],
'itemsProcFunc' => \VENDOR\MyExt\UserFunctions\FormEngine\TypeSelectProcFunc::class . '->fillSelect',
'customSetting' => 'somesetting'
]
and then access it in your class:
class TypeSelectProcFunc{
public function fillSelect(&$params){
if( $params['customSetting'] === 'somesetting' ){
$params['items'][] = ['New item',1];
}
}
}
I had a similar problem (also with itemsProcFunc and retrieving TypoScript). In my case, the current page ID of the selected backend page was not known to the ConfigurationManager. Because of this it used the page id of the root page (e.g. 1) and some TypoScript templates were not loaded.
However, before we look at the solution, Euli made some good points in his answer:
Do not use extbase configuration manager in TCA functions
Use TSconfig instead of TypoScript for backend configuration
You may like to ask another question what you are trying to do specifically and why you need TypoScript in BE context.
For completeness sake, I tested this workaround, but I wouldn't recommend it because of the mentioned reasons and because I am not sure if this is best practice. (I only used it because I was patching an extension which was already using TypoScript in the TCA and I wanted to find out why it wasn't working. I will probably rework this part entirely.)
I am posting this in the hope that it may be helpful for similar problems.
public function populateItemsProcFunc(array &$config): array
{
// workaround to set current page id for BackendConfigurationManager
$_GET['id'] = $this->getPageId((int)($config['flexParentDatabaseRow']['pid'] ?? 0));
$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$configurationManager = $objectManager->get(BackendConfigurationManager::class);
$setting = $configurationManager->getTypoScriptSetup();
$templates = $setting['plugin.']['tx_rssdisplay.']['settings.']['templates.'] ?? [];
// ... some code removed
}
protected function getPageId(int $pid): int
{
if ($pid > 0) {
return $pid;
}
$row = BackendUtility::getRecord('tt_content', abs($pid), 'uid,pid');
return $row['pid'];
}
The function getPageId() was derived from ext:news which also uses this in an itemsProcFunc but it then retrieves configuration from TSconfig. You may want to also look at that for an example: ext:news GeorgRinger\News\Hooks\ItemsProcFunc::user_templateLayout
If you look at the code in the TYPO3 core, it will try to get the current page id from
(int)GeneralUtility::_GP('id');
https://github.com/TYPO3/TYPO3.CMS/blob/90fa470e37d013769648a17a266eb3072dea4f56/typo3/sysext/extbase/Classes/Configuration/BackendConfigurationManager.php#L132
This will usually be set, but in an itemsProcFunc it may not (which was the case for me in TYPO3 10.4.14).

Set JSoup to connect only in english pages - How to?

I've tryed this solution here Jsoup set Accept-Language to make my JSoup connection only accept pages that come in english. Unfortunately it didn't work and my output was still:
I don't know if this happened because when the user agent says ("Accept-Language", "en") is to rather take english pages version instead of other languages or really for just accept the english ones. Anyway, the question speaks for itself, if there is a way to, how may I set the JSoup connection to only accept english pages?
Is it possible for you to write a language check method
public String languageCheck(String page){
String result = ""
List<String> pagesArray= new ArrayList<String>();
pagesArray.add(page);
if(pagesArray.get(0)!=null){
char []test = pagesArray.get(0).trim().toCharArray();
if(Character.isLetter(test[0]))
{
System.out.println("ok");
result = "okay"
}else{
System.out.println("Nok");
result = "Not Okay"
}
}
return result;
}
use this method to remove non English pages, hope it helps you

Server-side internationalization for Backbone and Handlebars

I'm working on a Grails / Backbone / Handlebars application that's a front end to a much larger legacy Java system in which (for historical & customizability reasons) internationalization messages are deep in a database hidden behind a couple of SOAP services which are in turn hidden behind various internal Java libraries. Getting at these messages from the Grails layer is easy and works fine.
What I'm wondering, though, is how to get (for instance) internationalized labels into my Handlebars templates.
Right now, I'm using GSP fragments to generate the templates, including a custom tag that gets the message I'm interested in, something like:
<li><myTags:message msgKey="title"/> {{title}}</li>
However, for performance and code layout reasons I want to get away from GSP templates and get them into straight HTML. I've looked a little into client-side internationalization options such as i18n.js, but they seem to depend on the existence of a messages file I haven't got. (I could generate it, possibly, but it would be ginormous and expensive.)
So far the best thing I can think of is to wedge the labels into the Backbone model as well, so I'd end up with something like
<li>{{titleLabel}} {{title}}</li>
However, this really gets away from the ideal of building the Backbone models on top of a nice clean RESTful JSON API -- either the JSON returned by the RESTful service is cluttered up with presentation data (i.e., localized labels), or I have to do additional work to inject the labels into the Backbone model -- and cluttering up the Backbone model with presentation data seems wrong as well.
I think what I'd like to do, in terms of clean data and clean APIs, is write another RESTful service that takes a list of message keys and similar, and returns a JSON data structure containing all the localized messages. However, questions remain:
What's the best way to indicate (probably in the template) what message keys are needed for a given view?
What's the right format for the data?
How do I get the localized messages into the Backbone views?
Are there any existing Javascript libraries that will help, or should I just start making stuff up?
Is there a better / more standard alternative approach?
I think you could create quite an elegant solution by combining Handelbars helpers and some regular expressions.
Here's what I would propose:
Create a service which takes in a JSON array of message keys and returns an JSON object, where keys are the message keys and values are the localized texts.
Define a Handlebars helper which takes in a message key (which matches the message keys on the server) and outputs an translated text. Something like {{localize "messageKey"}}. Use this helper for all template localization.
Write a template preprocessor which greps the message keys from a template and makes a request for your service. The preprocessor caches all message keys it gets, and only requests the ones it doesn't already have.
You can either call this preprocessor on-demand when you need to render your templates, or call it up-front and cache the message keys, so they're ready when you need them.
To optimize further, you can persist the cache to browser local storage.
Here's a little proof of concept. It doesn't yet have local storage persistence or support for fetching the texts of multiple templates at once for caching purposes, but it was easy enough to hack together that I think with some further work it could work nicely.
The client API could look something like this:
var localizer = new HandlebarsLocalizer();
//compile a template
var html = $("#tmpl").html();
localizer.compile(html).done(function(template) {
//..template is now localized and ready to use
});
Here's the source for the lazy reader:
var HandlebarsLocalizer = function() {
var _templateCache = {};
var _localizationCache = {};
//fetches texts, adds them to cache, resolves deferred with template
var _fetch = function(keys, template, deferred) {
$.ajax({
type:'POST',
dataType:'json',
url: '/echo/json',
data: JSON.stringify({
keys: keys
}),
success: function(response) {
//handle response here, this is just dummy
_.each(keys, function(key) { _localizationCache[key] = "(" + key + ") localized by server"; });
console.log(_localizationCache);
deferred.resolve(template);
},
error: function() {
deferred.reject();
}
});
};
//precompiles html into a Handlebars template function and fetches all required
//localization keys. Returns a promise of template.
this.compile = function(html) {
var cacheObject = _templateCache[html],
deferred = new $.Deferred();
//cached -> return
if(cacheObject && cacheObject.ready) {
deferred.resolve(cacheObject.template);
return deferred.promise();
}
//grep all localization keys from template
var regex = /{{\s*?localize\s*['"](.*)['"]\s*?}}/g, required = [], match;
while((match = regex.exec(html))) {
var key = match[1];
//if we don't have this key yet, we need to fetch it
if(!_localizationCache[key]) {
required.push(key);
}
}
//not cached -> create
if(!cacheObject) {
cacheObject = {
template:Handlebars.compile(html),
ready: (required.length === 0)
};
_templateCache[html] = cacheObject;
}
//we have all the localization texts ->
if(cacheObject.ready) {
deferred.resolve(cacheObject.template);
}
//we need some more texts ->
else {
deferred.done(function() { cacheObject.ready = true; });
_fetch(required, cacheObject.template, deferred);
}
return deferred.promise();
};
//translates given key
this.localize = function(key) {
return _localizationCache[key] || "TRANSLATION MISSING:"+key;
};
//make localize function available to templates
Handlebars.registerHelper('localize', this.localize);
}
We use http://i18next.com for internationalization in a Backbone/Handlebars app. (And Require.js which also loads and compiles the templates via plugin.)
i18next can be configured to load resources dynamically. It supports JSON in a gettext format (supporting plural and context variants).
Example from their page on how to load remote resources:
var option = {
resGetPath: 'resources.json?lng=__lng__&ns=__ns__',
dynamicLoad: true
};
i18n.init(option);
(You will of course need more configuration like setting the language, the fallback language etc.)
You can then configure a Handlebars helper that calls i18next on the provided variable (simplest version, no plural, no context):
// namespace: "translation" (default)
Handlebars.registerHelper('_', function (i18n_key) {
i18n_key = Handlebars.compile(i18n_key)(this);
var result = i18n.t(i18n_key);
if (!result) {
console.log("ERROR : Handlebars-Helpers : no translation result for " + i18n_key);
}
return new Handlebars.SafeString(result);
});
And in your template you can either provide a dynamic variable that expands to the key:
<li>{{_ titleLabeli18nKey}} {{title}}</li>
or specify the key directly:
<li>{{_ "page.fancy.title"}} {{title}}</li>
For localization of datetime we use http://momentjs.com (conversion to local time, formatting, translation etc.).

How can I find the current language in a Laravel view?

I'm using the Laravel Lang class for localization of my web app. I've added two languages to the languages array in application/config/application.php. This changes the default language it uses for localization to whatever the first part of the URI indicates (e.g. bla.com/en/bla and bla.com/co/bla). Now I need to be able to check what the current default language is in my view. However, the Lang class provides no way of checking this as far as I've been able to figure out, as the Lang::$language variable is protected. Is there any way of checking this apart from manually parsing the URI?
The cleanest way to know the current language of your website in Laravel appears to be :
Lang::locale();
https://laravel.com/api/5.8/Illuminate/Translation/Translator.html#method_locale
It's different than this command that will return the default language of your website :
Config::get('app.locale');
An alternative, a bit shorter way could be using something like this:
app()->getLocale()
The advantage of this is that IDEs such as PHPStorm recognize this function and can help you develop much faster.
BenjaminRH's answer is very good, and his suggested approach works perfectly. I've improved the snippet a bit. Now it detects the browser language and checks if that language is supported according to the application's config file.
It's a quick hack, but it works on my app. Note that the application language is also set now. Feel free to use ore improve it.
Route::filter('before', function()
{
// current uri language ($lang_uri)
$lang_uri = URI::segment(1);
// Set default session language if none is set
if(!Session::has('language'))
{
// use lang in uri, if provided
if(in_array($lang_uri, Config::get('application.languages')))
{
$lang = $lang_uri;
}
// detect browser language
elseif(isset(Request::server('http_accept_language')))
{
$headerlang = substr(Request::server('http_accept_language'), 0, 2);
if(in_array($headerlang, Config::get('application.languages')))
{
// browser lang is supported, use it
$lang = $headerlang;
}
// use default application lang
else
{
$lang = Config::get('application.language');
}
}
// no lang in uri nor in browser. use default
else
{
// use default application lang
$lang = Config::get('application.language');
}
// set application language for that user
Session::put('language', $lang);
Config::set('application.language', $lang);
}
// session is available
else
{
// set application to session lang
Config::set('application.language', Session::get('language'));
}
// prefix is missing? add it
if(!in_array($lang_uri, Config::get('application.languages')))
{
return Redirect::to(URI::current());
}
// a valid prefix is there, but not the correct lang? change app lang
elseif(in_array($lang_uri, Config::get('application.languages')) AND $lang_uri != Config::get('application.language'))
{
Session::put('language', $lang_uri);
Config::set('application.language', $lang_uri);
}
});
In the newer Laravel versions, you can get the current language with:
Config::get('app.locale');
This would work fine
lang="{{ app()->getLocale() }}"
I've figured out a solution to the language problem (thanks to nickstr on the IRC and the accepted answer to this question). It involves storing the current language as a session variable, which is updated when the language uri segment is changed.
Route::filter('before', function()
{
// Do stuff before every request to your application...
// Default language ($lang) & current uri language ($lang_uri)
$lang = 'he';
$lang_uri = URI::segment(1);
// Set default session language if none is set
if(!Session::has('language'))
{
Session::put('language', $lang);
}
// Route language path if needed
if($lang_uri !== 'en' && $lang_uri !== 'he')
{
Return Redirect::to($lang.'/'.URI::current());
}
// Set session language to uri
elseif($lang_uri !== Session::get('language'))
{
Session::put('language', $lang_uri);
}
});
This might help.
Config::get('application.language')
You can use
https://github.com/mcamara/laravel-localization
Laravel Localization uses the URL given for the request. In order to achieve this purpose, a group should be added into the routes.php file. It will filter all pages that must be localized.
// app/routes.php
Route::group(array('prefix' => LaravelLocalization::setLanguage()), function()
{
/** ADD ALL LOCALIZED ROUTES INSIDE THIS GROUP **/
Route::get('/', function()
{
return View::make('hello');
});
Route::get('test',function(){
return View::make('test');
});
});
/** OTHER PAGES THAT SHOULD NOT BE LOCALIZED **/
Once this group is added to the routes file, an user can access to all languages added into the 'languagesAllowed' ('en' and 'es' for default, look at the config section to change that option). For example, an user can now access to two different languages, using the following addresses:
http://laravel.com/en
http://laravel.com/es
http://laravel.com
I use App::getLocale() which is probably the most supported way as the App::setLocale('EN') method is used in the documentation.
You can use this method everywhere. If it throughs an error somewhere, you can use \App::... to make it work.
I'm using Laravel 5.0.
Your can get current language in laravel blade by:
{{Lang::locale()}}
The Lang class is specifically for outputting the correct language and as you say manages the language internally.
Looking through the API there is no method to help you directly with this and parsing the URI to get the language would seem the appropriate course of action.
You can always just do this to retrieve the language string in the URI:
$language = URI::segment(1);
Examining Laravel Requests

Magento multilanguage - double change in language resuts in 404 (or how to change language within stores not views)

I have a problem with a magento installation. I used Magento ver. 1.5.0.1, community edition to develop this website http://cissmarket.com/.
The problem appears when I change the language from the EU version to French and after that to German. The change to french is ok, but when in the same page i change to German i receive a 404 error. Also this is generation 404 errors in the Google webmaster tools and when i try for example to take this link and paste it in the browser it gives me also a 404 error. I have there some 50 products and ~550 404 errors in Google Webmaster tools. I understand that the problem is from what I described.
Moreover I have a SEO problem since I have this page in french:
http://cissmarket.com/de/cartouches-refilables.html
And when I switch to the german version of the website it takes me to this link
http://cissmarket.com/de/cartouches-refilables.html?___from_store=fr (if i try now to switch to uk I will get the 404 mentioned above)
instead of going to this one:
http://cissmarket.com/de/nachfullpatronen.html
Already checked this 404 error when switching between stores when in a category on magento but it does not relate to my problem.
About settings:
I use the caching service and also I did index all the content.
The product or category I am trying to access is available and set active for all the languages.
System > General > Web > URL options > Add Store Code to Urls is set
to yes.
System > General > Web > Search Engines Optimization > Use Web Server
Rewrites is set to yes.
No other changes has been made to the .htaccess file except for the
ones that the system itself made.
So to conclude: the problem is the 404 given by 2 succesive changes of the language and the bad url address when I switch from one page to another.
Any suggestions would be appreciated.
UPDATE: tried this http://www.activo.com/how-to-avoid-the-___from_store-query-parameter-when-switching-store-views-in-magento but it results in a 404 at the first language change
Edit #1:
Found the problem: file languages.phtml contained this code <?php echo str_replace ("/fr/","/de/",$_lang->getCurrentUrl()); ?> and actually did replace only the language code and not the whole url according to the corresponding translation.
So applied to this
http://cissmarket.com/fr/cartouches-refilables.html
it will return
http://cissmarket.com/de/cartouches-refilables.html
So does anyone know how to get the corresponding URL of the current page for the other languages available in the store?
Edit #2 (using #Vinai solution):
It works on the product pages but not on the category yet.
There is no such thing in the native Magento as far as I know.
That said, you can use the following code to get the current page URL for each store.
$resource = Mage::getSingleton('core/resource');
$requestPath = Mage::getSingleton('core/url')->escape(
trim(Mage::app()->getRequest()->getRequestString(), '/')
);
$select = $resource->getConnection('default_read')->select()
->from(array('c' => $resource->getTableName('core/url_rewrite')), '')
->where('c.request_path=?', $requestPath)
->where('c.store_id=?', Mage::app()->getStore()->getId())
->joinInner(
array('t' => $resource->getTableName('core/url_rewrite')),
"t.category_id=c.category_id AND t.product_id=c.product_id AND t.id_path=c.id_path",
array('t.store_id', 't.request_path')
);
$storeUrls = (array) $resource->getConnection('default_read')
->fetchPairs($select);
This will give you an array with the array key being the store IDs and the array values being the request path after the Magento base URL, e.g. assuming your French store has the ID 1 and the German one has the ID 2, you would get:
Array
(
[1] => cartouches-refilables.html
[2] => nachfullpatronen.html
)
Then, in the foreach loop where the URL for each store is output, use
<?php $url = isset($storeUrls[$_lang->getId()]) ? $_lang->getUrl($storeUrls[$_lang->getId()]) : $_lang->getCurrentUrl() ?>
The call to $_lang->getUrl() will add the base URL, so you will get the full URL for each store (e.g. http://cissmarket.com/de/nachfullpatronen.html). If no store view value is found in the core_url_rewrite table it will revert to the default behaviour.
You still need the ___store=fr query parameter because otherwise Magento will think you are trying to access the new path in the context of the old store. Luckily, the getUrl() call an the store model adds that for you automatically.
The code querying the database can be anywhere of course (since its PHP), even in the template, but please don't put it there. The correct place to have code that access the database is a resource model. I suggest you create a resource model and put it in a method there.
I've found an ugly patch until a better approach comes up.
In the admin section, i've added the following javascript inside the wysiwyg in CMS > PAGES > (My 404 pages) (at the beginning of the wysiwyg) :
<script type="text/javascript" language="javascript">// <![CDATA[
var lang = "en";
var rooturl = "{{config path="web/unsecure/base_url"}}"
var url = document.location.href;
if(!(url.match("/"+lang+"/")))
{
var newUrl = url.replace(rooturl , rooturl+lang+"/" );
window.location.href = newUrl;
}
// ]]></script>
(Note: you need to do this for all of your translated 404 pages. In each 404 page you need to modify lang="en" for your storeview url value)
Because the wysiwyg (tiny_mce) does not allow javascript to be threated, you'll have to modify js/mage/adminhtml/wysiwyg/tinymce/setup.js. Add the following code under line 97 (under "var settings = "):
extended_valid_elements : 'script[language|type|src]',
For Magento 1.7.0.2 and 1.8.0.0 this is the bugfix:
Starting from line 251 of /app/code/core/Mage/Core/Model/Url/Rewrite.php
:
Mage::app()->getCookie()->set(Mage_Core_Model_Store::COOKIE_NAME, $currentStore->getCode(), true);
// endur 02-03-2013 fix for missed store code
// $targetUrl = $request->getBaseUrl(). '/' . $this->getRequestPath();
if (Mage::getStoreConfig('web/url/use_store') && $storeCode = Mage::app()->getStore()>getCode()) {
$targetUrl = $request->getBaseUrl(). '/' . $storeCode . '/' .$this->getRequestPath();
} else {
$targetUrl = $request->getBaseUrl(). '/' . $this->getRequestPath();
}
// endur 02-03-2013 end
Make sure to create a custom copy of the file in:
/app/code/local/Mage/Core/Model/Url/Rewrite.php or:
/app/code/local/YourTheme/Mage/Core/Model/Url/Rewrite.php
source:
It looks like a bug in Magento 1.7. Here is a hack that worked for me.
It should work for a two language store with store code in URL
in var/www/html/shop1/app/code/core/Mage/Core/Model/Url/Rewrite.php
remove this line
// $targetUrl = $request->getBaseUrl(). '/' . $this->getRequestPath();
and add these:
$storecode = Mage::app()->getStore()->getCode();
if ($storecode='en')
{
$targetUrl = $request->getBaseUrl(). '/'.$storecode.'/' . $this->getRequestPath();
}
else
{
$targetUrl = $request->getBaseUrl(). '/' . $this->getRequestPath();
}
Here a another solution for this problem. Just add this code after "$this->load($pathInfo, 'request_path');" in app/code/core/Mage/Core/Model/Url/Rewrite.php:
if (!$this->getId() && !isset($_GET['___from_store'])) {
$db = Mage::getSingleton('core/resource')->getConnection('default_read');
$result = $db->query('select store_id from core_url_rewrite WHERE request_path = "' . $pathInfo . '"');
if ($result) {
$storeIds = array();
if($row = $result->fetch(PDO::FETCH_ASSOC)) {
$storeId = $row['store_id'];
$storeCode = Mage::app()->getStore($storeId)->getCode();
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://" . $_SERVER['HTTP_HOST'] . "/" . $pathInfo . "?___store=" . $storeCode);
exit();
}
}
}
guys. For this error there is magento module. It have rewrite 2 models
http://www.magentocommerce.com/magento-connect/fix-404-error-in-language-switching.html

Resources