Yii framework multi language, multi top level domain - yii

My goal is to have this:
.com/english-urls - English (United States)
.com.br/portuguess-urls - Portuguess (Brazil)
.com.mx/spanish-urls - Spanish (México)
...
I already have working multilingual functionality using this Language Switcher: http://www.yiiframework.com/wiki/293/manage-target-language-in-multilingual-applications-a-language-selector-widget-i18n/
And URL localization using this: http://www.yiiframework.com/wiki/55/i18n-subdomains-and-url-rules/
Any idea on how to have the multi top level domain functionality?
Thanks in advance to contribute to Yii development.

There are a few different ways you can approach this.
Parameterized host names. See the guide for details on how to set it up: http://www.yiiframework.com/doc/guide/1.1/en/topics.url#parameterizing-hostnames
Use environment variables set as part of your web server depending on the domain name being used.
I've done #1 in the past and it works pretty well. One nasty side effect comes up if you have a site that runs with SSL but your devs work with non-SSL machines. Parameterized host names require the full http:// or https:// as part of the URL rule unless you extend CUrlManager.
Another bug I hit recently occurs if you use parameterized hostnames AND a baseUrl (https://github.com/yiisoft/yii/issues/3520). Probably not something to worry about, but an FYI that it is there.
Which is why the idea of using environment variables intrigues me. You might be able to load only rule sets that match your given language, etc. but I haven't personally built a system using that approach.

Finally I got a solution!
Using this class: http://www.yiiframework.com/wiki/55/i18n-subdomains-and-url-rules/
1.- Define your top level domains list.
public $domainList = array('www.example.com.mx' => 'es', 'www.example.com' => 'en');
2.- Comment the unnesesary code.
3.- Detect SERVER_NAME and save as activeLanguage.
$languageCode = $this->domainList[$_SERVER['SERVER_NAME']];
$this->activeLanguage = $this->isSupportedLanguage($languageCode);
3.- Create the links in your header or main.
Thanks to twitter.com/atrandafir and acorncom for contribute!

Related

How can I run Zend Framework code alongside legacy (non-ZF) code on the same server on the same HTTP port?

I have a large codebase that I am trying to eventually convert to Zend-Framework-powered stack.
I at times write new modules to where I have a choice:
keep writing using legacy routing/initialization/etc
somehow figure out how to use ZF for the new module only while the rest of the legacy code works "as before"
Is this possible?
How?
To give you an idea, code I have now uses proprietary multiple routing files, where everything in ZF goes through one single router file.
So legacy code is called like so i.e.:
http://legacy:80/index.php?route=product
May be similar to zend framework 2 in a subdirectory
Zend Middleware approach
I was able to follow https://docs.zendframework.com/zend-mvc/middleware/ and implement an IndexMiddleware class. I can see that IndexMiddleware::process() method is being called. But I am not certain how to go further, and how to engage my legacy web application to return data as before.
MiddlewareListener.
Legacy App - index.php
$module = filter($_GET['p']);
if (!empty($module))
$inc = 'portal/{$module}.php'; //prep a legacy module
require($inc); //run module
There are many solutions there... Depends on how much new code you have, and addresses you want.
Long story short, you could work at the server level (aliases, rewrite, etc), or at the PHP code level.
Something you could do is use the index.php from the Zend Skeleton for instance, and the default url routing through index.php. Then look at the application lifecycle, especially the route event. I believe that's a good point to add a listener that would dispatch the old application. You can find numbers of Listeners in the Zend MVC code to base your code on (look at the middleware one for instance).

Adding a second webapp

I am struggling to setup a public website in Moqui, I am trying to have (dev-)www.example.net as the public marketing site and signup forms. Then the tennants on [tennant-name].example.net I have setup a basic component and then edited MoquiDevConf.xml, modified the webapp-list as shown below:
<webapp-list>
<webapp name="webpublic" http-port="8080" https-enabled="false">
<root-screen host="dev-www.example.net" location="component://webpublic/screen/webpublic.xml"/>
</webapp>
<webapp name="webroot" http-port="8080" https-enabled="false">
<root-screen host="^((?!dev-www.example.net).)*$" location="component://webroot/screen/webroot.xml"/>
</webapp>
</webapp-list>
I have restarted the app for the changes to take effect but all I get is an error 500 when I try and visit http://dev-www.example.net:8080/
org.moqui.BaseException: Could not find root screen for host [dev-www.example.net]
As far as I can tell Moqui is finding the component as I see this in the logs:
Added component [webpublic] at [file:/Volumes/MacHDD/Sources/atlas-moqui/runtime/component/webpublic]
Non dev-www hosts still work and I get the customary login screen so I am not sure what I am missing as this is almost a direct copy of the existing webroot?
Thanks for any help!
Sam
You probably using the same port number. Try different one (e.g. 8081) for the second one. All used ports should be different. Please see my comment as well.
My guess about why your particular configuration is not working is that the root-screen.#host attribute is always a regular expression and the URL you are using contains special characters including '-' and '.'. It should work if you escape these characters with a '\', i.e. use '.' and '-'.
That said, if you want to support virtual hosts with the same webapp root for multiple tenants you shouldn't need to declare the virtual hosts this way, this is only needed if you want a different webapp root screen (which may be what you eventually want to do).
UPDATE: With the configuration snippet above the issue is that there are multiple webapp-list.webapp elements, one with name=webroot which is the webapp used (as specified in the web.xml file in the moqui-name context-param) and the other with name=webpublic which is ignored because the configuration is found based on the name from the web.xml file.
The solution is to put both root-screen elements under the webapp element with name=webroot. Basically the way these are looked up is not arbitrary, it is explicit for the webapp name (the moqui-name context-param). If you have multiple webapps deployed they should have different moqui-name values to refer to different configurations. This would best be done in something other that Winstone, something like Tomcat. It would also stray from the documented ways of deploying Moqui, so a bit more work would need to be done. There isn't any really point in doing this, better to run everything in the same webapp with multiple root-screen elements and multiple root screens as needed.

Support for multiple environments in your windows store app

I have been working on a Windows Store app where I have to support multiple configuration parameters for my app. One of the parameters is the URL the app is talking to.
For example development environment, test, acceptance and finally production.
One of the things i'm currently thinking about is what is the most efficient way of supporting all these environments with the least effort. Because there isn't some kind of config file that we can change to update these parameters I came up with some ideas. I'm curious about other options that I might have not seen.
Here are the things I came up with:
1
Adding multiple configuration to the app and than using them in code to get the correct parameter like this:
private string webserviceUrl;
#if DEV
webserviceUrl = "devUrl";
#elif TEST
webserviceUrl = "testUrl";
#endif
2
With the approach in number 1 there are a few more options available like including a config xml file bases on the configuration, or fetching configuration settings from a webservice the first time the app is running.
3
Using a branch/merge strategy and update the config files in the branch. Advantage is that the code is clean and only contains the settings it needs for the build it's created for. And the package can be build by the build server. Disadvantage is that you need to branch/merge alot.
The last option feels like the most 'clean' solution to do this. Am I missing any options, or do you have experience with any of these methods? What would you prefer?
I think the assumption is that apps in the store will always point to production.
But, in saying that, I'm facing the same issue as we're side loading the application onto devices that we control, and not using the Windows Store at all.
To answer your question, I prefer option 1.
Option 2 and the xml/json config file seems like the best option though.
The webservice option probably won't work. What webservice URL do you use? And how will it work if you want some instances pointing to different environments as they will all be fetching the config from the same URL.
Another option you might want to consider would be options in the settings charm menu. For example, use radio buttons for the environments, and allow the user to configure which environment they want to target.
The issue would be locking it down in production for end users so that it isn't modifiable any more. Perhaps once "PROD" radio is selected, all the radio buttons are then hidden.
If you're deploying the application through side loading, then these settings could probably be configured during the install process.
I'd be interested to hear other opinions as well. This is also an old question, so I'd like to know what solution you decided on implementing.

returning absolute vs relative URIs in REST API

suppose the DogManagementPro program is an application written in client/server architecture, where the customers who buys it is supposed to run the server on his own PC, and access it either locally or remotely.
suppose I want to support a "list all dogs" operations in the DogManagementPro REST API.
so a GET to http://localhost/DogManagerPro/api/dogs should fetch the following response now:
<dogs>
<dog>http://localhost/DogManagerPro/api/dogs/ralf</dog>
<dog>http://localhost/DogManagerPro/api/dogs/sparky</dog>
</dogs>
where I want to access it remotely on my local LAN, [the local IP of my machine is 192.168.0.33]
what should a a GET to http://192.168.0.33:1234/DogManagerPro/api/dogs fetch?
should it be:
<dogs>
<dog>http://localhost/DogManagerPro/api/dogs/ralf</dog>
<dog>http://localhost/DogManagerPro/api/dogs/sparky</dog>
</dogs>
or perhaps:
<dogs>
<dog>http://192.168.0.33/DogManagerPro/api/dogs/ralf</dog>
<dog>http://192.168.0.33/DogManagerPro/api/dogs/sparky</dog>
</dogs>
?
some people argue that I should subside the problem altogether by returning just a path element like so:
<dogs>
<dog>/DogManagerPro/api/dogs/ralf</dog>
<dog>/DogManagerPro/api/dogs/sparky</dog>
</dogs>
what is the best way?
I've personally always used non-absolute urls. It solves a few other problems as well, such as reverse / caching proxies.
It's a bit more complicated for the client though, and if they want to store the document as-is, it may imply they also now need to store the base url, or expand the inner urls.
If you do choose to go for the full-url route, I would not recommend using HTTP_HOST, but setup multiple vhosts, and environment variable and use that.
This solves the issue if you later on need proxies in front of your origin server.
I would say absolute URLs created based on the Host header that the client sent
<dogs>
<dog>http://192.168.0.33:1234/DogManagerPro/api/dogs/ralf</dog>
<dog>http://192.168.0.33:1234/DogManagerPro/api/dogs/sparky</dog>
</dogs>
The returned URIs should be something the client is able to resolve.

Modern File Structuring for Website Development

So I am fairly new to website development, PHP, Mysql, etc. so it's a given if I get some downvotes for my sheer lack of intelligence, I just want the answer haha.
I have probably jumped the band wagon or probably inherited a completely bad coding practice; instead of simplistic website structures such as stackoverflow.com/questions.php?q=ask (displaying content based on GET data), or making it even more simplistic such as stackoverflow.com/ask.php, etc, we have the seemingly straight forward stackoverflow.com/questions/ask
So what's the weird magic going on?
It's likely you're looking for mod_rewrite.
mod_rewrite will work but it really won't improve your actual file structure on the site (behind the scenes.)
For that you would use a PHP framework. I would suggest starting with CodeIgniter which is simpler than Zend. (I don't have experience with CakePHP so I won't comment on that.)
You will need to configure routing to trap a url so that it maps to a certain controller the use a function to capture the rest of the url as parameters.
function _remap($params = array()) {
return call_user_func_array(array($this, 'index'), $params);
}
Then, in the same controller change the index function like this:
function index($id = null) {
$data['question'] = /* get your data from the database */;
$this->load->view('index', $data);
return true;
}
This assumes you started with the welcome controller example in the zip file.
But, to answer your question more directly, there isn't really any magic going on. The browser is requesting a certain resource and the server is returning that resource according to it's own logic and how it is configured. The layout of files on the server is an internal issue, the browser only sees the representation of the server's state. Read up on the REST principle to understand this better.