Codeigniter Internationalization i18n trailing slash not added - codeigniter

I have a project going on, and now [admin section is almost done] (I know bit late) I am trying to implement i18n to the project.
I think everything works fine except when I enter http://localhost/my_project while my_project is working directory with CI installation in it, I am redirected to the following http://localhost/my_project/enhome (no trailing slash after en) any ideas?
Expecting result http://localhost/my_project/en/home, not just home controller but all controllers are behaving same.
.htaccess, base_url and index_page are set right (all works without the i18n).
routes.php are out of stock
$route['default_controller'] = "home";
$route['404_override'] = '';
// URI like '/en/about' -> use controller 'about'
$route['^(en|de|fr|nl)/(.+)$'] = "$2";
// '/en', '/de', '/fr' and '/nl' URIs -> use default controller
$route['^(en|de|fr|nl)$'] = $route['default_controller'];
edit
I am using "new" i18n from I guess ellislab. Sorry for wrong link (for 1.7 CI version).

So after some digging, I found the problem in core file, on the bottom of this posted script there is variable $new_url and it was echoing Redirect triggered to http://192.168.1.184/my_project/enhome without the "fix". I just added the / in there and it works prefectly I wonder what happend here and if this is OK fix or not.
function MY_Lang() {
parent::__construct();
global $CFG;
global $URI;
global $RTR;
$this->uri = $URI->uri_string();
$this->default_uri = $RTR->default_controller;
$uri_segment = $this->get_uri_lang($this->uri);
$this->lang_code = $uri_segment['lang'] ;
$url_ok = false;
if ((!empty($this->lang_code)) && (array_key_exists($this->lang_code, $this->languages)))
{
$language = $this->languages[$this->lang_code];
$CFG->set_item('language', $language);
$url_ok = true;
}
if ((!$url_ok) && (!$this->is_special($uri_segment['parts'][0]))) // special URI -> no redirect
{
// set default language
$CFG->set_item('language', $this->languages[$this->default_lang()]);
$uri = (!empty($this->uri)) ? $this->uri: $this->default_uri;
//OPB - modification to use i18n also without changing the .htaccess (without pretty url)
$index_url = empty($CFG->config['index_page']) ? '' : $CFG->config['index_page']."/";
$new_url = $CFG->config['base_url'].$index_url.$this->default_lang()."/".$uri;
echo "Redirect triggered to ".$new_url;
//header("Location: " . $new_url, TRUE, 302);
// exit;
}
}

this library is little old never been updated author since long time and it works for CI 1.7 but here is updated version compatible with CI 2.1.* same library but updated version working same way you can download from here
CodeIgniter 2.1 internationalization i18n

Related

Laravel session suddenly not being saved

Yesterday it was working fine, but somehow today it's not saving the array to the session.
if(Session::get('header')) {
$array['header'] = Session::get('header');
} else {
$header = $this->loadElements(2, false);
$array['header'] = $header;
Session::put('header', $header);
}
When I look in the storage\framework\sessions folder, the header is in the latest session file.
But what looks very weird to me, is that when having the browser window still open, on each page reload a new session file is created, which is very odd to me.
I did some further testing and it has nothing to do with my code, but all with the recreation of sessions after each page load. In another project it works fine, so it must have to do with the recreation.
Why is Laravel all of a sudden not reading the session file and thus recreating it?
In config\session.php I changed 'driver' => env('SESSION_DRIVER', 'file') to database and back, and then it works again.
Smh
Rewrite your code to use Session::has in your condition rather than get.
if(Session::has('header')) {
$array['header'] = Session::get('header');
} else {
$header = $this->loadElements(2, false);
$array['header'] = $header;
Session::put('header', $header);
}

Auto-updates to Electron

I'm looking to deploy an auto-update feature to an Electron installation that I have, however I am finding it difficult to find any resources on the web.
I've built a self contained application using Adobe Air before and it seemed to be a lot easier writing update code that effectively checked a url and automatically downloaded and installed the update across Windows and MAC OSX.
I am currently using the electron-boilerplate for ease of build.
I have a few questions:
How do I debug the auto update feature? Do I setup a local connection and test through that using a local Node server or can I use any web server?
In terms of signing the application I am only looking to run apps on MAC OSX and particularly Windows. Do I have to sign the applications in order to run auto-updates? (I managed to do this with Adobe Air using a local certificate.
Are there any good resources that detail how to implement the auto-update feature? As I'm having difficulty finding some good documentation on how to do this.
I am also new to Electron but I think there is no simple auto-update from electron-boilerplate (which I also use). Electron's auto-updater uses Squirrel.Windows installer which you also need to implement into your solution in order to use it.
I am currently trying to use this:
https://www.npmjs.com/package/electron-installer-squirrel-windows
And more info can be found here:
https://github.com/atom/electron/blob/master/docs/api/auto-updater.md
https://github.com/squirrel/squirrel.windows
EDIT: I just opened the project to try it for a while and it looks it works. Its pretty straightforward. These are pieces from my gulpfile.
In current configuration, I use electron-packager to create a package.
var packager = require('electron-packager')
var createPackage = function () {
var deferred = Q.defer();
packager({
//OPTIONS
}, function done(err, appPath) {
if (err) {
gulpUtil.log(err);
}
deferred.resolve();
});
return deferred.promise;
};
Then I create an installer with electron-installer-squirrel-windows.
var squirrelBuilder = require('electron-installer-squirrel-windows');
var createInstaller = function () {
var deferred = Q.defer();
squirrelBuilder({
// OPTIONS
}, function (err) {
if (err)
gulpUtil.log(err);
deferred.resolve();
});
return deferred.promise;
}
Also you need to add some code for the Squirrel to your electron background/main code. I used a template electron-squirrel-startup.
if(require('electron-squirrel-startup')) return;
The whole thing is described on the electron-installer-squirrel-windows npm documentation mentioned above. Looks like the bit of documentation is enough to make it start.
Now I am working on with electron branding through Squirrel and with creating appropriate gulp scripts for automation.
You could also use standard Electron's autoUpdater module on OS X and my simple port of it for Windows: https://www.npmjs.com/package/electron-windows-updater
I followed this tutorial and got it working with my electron app although it needs to be signed to work so you would need:
certificateFile: './path/to/cert.pfx'
In the task config.
and:
"build": {
"win": {
"certificateFile": "./path/to/cert.pfx",
"certificatePassword": "password"
}
},
In the package.json
Are there any good resources that detail how to implement the auto-update feature? As I'm having difficulty finding some good documentation on how to do this.
You don't have to implement it by yourself. You can use the provided autoUpdater by Electron and just set a feedUrl. You need a server that provides the update information compliant to the Squirrel protocol.
There are a couple of self-hosted ones (https://electronjs.org/docs/tutorial/updates#deploying-an-update-server) or a hosted service like https://www.update.rocks
Question 1:
I use Postman to validate that my auto-update server URLs return the response I am expecting. When I know that the URLs provide the expected results, I know I can use those URLs within the Electron's Auto Updater of my Application.
Example of testing Mac endpoint with Postman:
Request:
https://my-server.com/api/macupdates/checkforupdate.php?appversion=1.0.5&cpuarchitecture=x64
JSON Response when there is an update available:
{
"url": "https:/my-server.com/updates/darwin/x64/my-electron=app-x64-1.1.0.zip",
"name": "1.1.0",
"pub_date": "2021-07-03T15:17:12+00:00"
}
Question 2:
Yes, your Electron App must be code signed to use the auto-update feature on Mac. On Windows I'm not sure because my Windows Electron app is code signed and I did not try without it. Though it is recommended that you sign your app even if the auto-update could work without it (not only for security reasons but mainly because otherwise your users will get scary danger warnings from Windows when they install your app for the first time and they might just delete it right away).
Question 3:
For good documentation, you should start with the official Electron Auto Updater documentation, as of 2021-07-07 it is really good.
The hard part, is figuring out how to make things work for Mac. For Windows it's a matter of minutes and you are done. In fact...
For Windows auto-update, it is easy to setup - you just have to put the RELEASES and nupkg files on a server and then use that URL as the FeedURL within your Electron App's autoUpdater. So if your app's update files are located at https://my-server.com/updates/win32/x64/ - you would point the Electron Auto Updater to that URL, that's it.
For Mac auto-update, you need to manually specify the absolute URL of the latest Electron App .zip file to the Electron autoUpdater. So, in order to make the Mac autoUpdater work, you will need to have a way to get a JSON response in a very specific format. Sadly, you can't just put your Electron App's files on your server and expect it to work with Mac just like that. Instead, the autoUpdater needs a URL that will return the aforementioned JSON response. So to do that, you need to pass Electron's Auto Updater feedURL the URL that will be able to return this expected kind of JSON response.
The way you achieve this can be anything but I use PHP just because that's the server I already paid for.
So in summary, with Mac, even if your files are located at https://my-server.com/updates/darwin/x64/ - you will not provide that URL to Electron's Auto Updater FeedURL. Instead will provide another URL which returns the expected JSON response.
Here's an example of my main.js file for the Electron main process of my App:
// main.js (Electron main process)
function registerAutoUpdater() {
const appVersion = app.getVersion();
const os = require('os');
const cpuArchitecture = os.arch();
const domain = 'https://my-server.com';
const windowsURL = `${domain}/updates/win32/x64`;
const macURL = `${domain}/api/macupdates/checkforupdate.php?appversion=${appVersion}&cpuarchitecture=${cpuArchitecture}`;
//init the autoUpdater with proper update feed URL
const autoUpdateURL = `${isMac ? macURL : windowsURL}`;
autoUpdater.setFeedURL({url: autoUpdateURL});
log.info('Registered autoUpdateURL = ' + (isMac ? 'macURL' : 'windowsURL'));
//initial checkForUpdates
autoUpdater.checkForUpdates();
//Automatic 2-hours interval loop checkForUpdates
setInterval(() => {
autoUpdater.checkForUpdates();
}, 7200000);
}
And here's an example of the checkforupdate.php file that returns the expected JSON response back to the Electron Auto Updater:
<?php
//FD Electron App Mac auto update API endpoint.
// The way Squirrel.Mac works is by checking a given API endpoint to see if there is a new version.
// If there is no new version, the endpoint should return HTTP 204. If there is a new version,
// however, it will expect a HTTP 200 JSON-formatted response, containing a url to a .zip file:
// https://github.com/Squirrel/Squirrel.Mac#server-support
$clientAppVersion = $_GET["appversion"] ?? null;
if (!isValidVersionString($clientAppVersion)) {
http_response_code(204);
exit();
}
$clientCpuArchitecture = $_GET["cpuarchitecture"] ?? null;
$latestVersionInfo = getLatestVersionInfo($clientAppVersion, $clientCpuArchitecture);
if (!isset($latestVersionInfo["versionNumber"])) {
http_response_code(204);
exit();
}
// Real logic starts here when basics did not fail
$isUpdateVailable = isUpdateAvailable($clientAppVersion, $latestVersionInfo["versionNumber"]);
if ($isUpdateVailable) {
http_response_code(200);
header('Content-Type: application/json;charset=utf-8');
$jsonResponse = array(
"url" => $latestVersionInfo["directZipFileURL"],
"name" => $latestVersionInfo["versionNumber"],
"pub_date" => date('c', $latestVersionInfo["createdAtUnixTimeStamp"]),
);
echo json_encode($jsonResponse);
} else {
//no update: must respond with a status code of 204 No Content.
http_response_code(204);
}
exit();
// End of execution.
// Everything bellow here are function declarations.
function getLatestVersionInfo($clientAppVersion, $clientCpuArchitecture): array {
// override path if client requests an arm64 build
if ($clientCpuArchitecture === 'arm64') {
$directory = "../../updates/darwin/arm64/";
$baseUrl = "https://my-server.com/updates/darwin/arm64/";
} else if (!$clientCpuArchitecture || $clientCpuArchitecture === 'x64') {
$directory = "../../updates/darwin/";
$baseUrl = "https://my-server.com/updates/darwin/";
}
// default name with version 0.0.0 avoids failing
$latestVersionFileName = "Finance D - Tenue de livres-darwin-x64-0.0.0.zip";
$arrayOfFiles = scandir($directory);
foreach ($arrayOfFiles as $file) {
if (is_file($directory . $file)) {
$serverFileVersion = getVersionNumberFromFileName($file);
if (isVersionNumberGreater($serverFileVersion, $clientAppVersion)) {
$latestVersionFileName = $file;
}
}
}
return array(
"versionNumber" => getVersionNumberFromFileName($latestVersionFileName),
"directZipFileURL" => $baseUrl . rawurlencode($latestVersionFileName),
"createdAtUnixTimeStamp" => filemtime(realpath($directory . $latestVersionFileName))
);
}
function isUpdateAvailable($clientVersion, $serverVersion): bool {
return
isValidVersionString($clientVersion) &&
isValidVersionString($serverVersion) &&
isVersionNumberGreater($serverVersion, $clientVersion);
}
function getVersionNumberFromFileName($fileName) {
// extract the version number with regEx replacement
return preg_replace("/Finance D - Tenue de livres-darwin-(x64|arm64)-|\.zip/", "", $fileName);
}
function removeAllNonDigits($semanticVersionString) {
// use regex replacement to keep only numeric values in the semantic version string
return preg_replace("/\D+/", "", $semanticVersionString);
}
function isVersionNumberGreater($serverFileVersion, $clientFileVersion): bool {
// receives two semantic versions (1.0.4) and compares their numeric value (104)
// true when server version is greater than client version (105 > 104)
return removeAllNonDigits($serverFileVersion) > removeAllNonDigits($clientFileVersion);
}
function isValidVersionString($versionString) {
// true when matches semantic version numbering: 0.0.0
return preg_match("/\d\.\d\.\d/", $versionString);
}

Grails change locale

How to change locale in grails application and force the browser to use the same. I tried this solution.
def locale = new Locale("de","DE")
RequestContextUtils.getLocaleResolver(request).setLocale(request, response, locale)
Also tried to change browser location as well nothing worked.
Any suggestions?
You could make use of params.lang. I use a grails filter to set the language on every request, e.g.
languageFilter(controller: '*', action: '*')
{
before = {
params.lang = "de"
return true;
}
}

Inconsistent CodeIgniter routes.php behaviour

I'm using CodeIgniter's routes file to remap short urls to their relevant controller functions.
Oddly enough, some urls get remapped, while others don't, even though the syntax is identical.
Below is my routes.php file. The remapping of info/web and info/rent works as expected, while info/cell and info/hotel gets redirected to my 404 function.
Any idea what could be causing it?
$route['default_controller'] = "home";
$route['404_override'] = 'home/four_o_four';
$route['robots.txt'] = 'home/robots';
$route['info/cell'] = "articles/tags/cellphone";
$route['info/rent'] = "articles/tags/car-rental";
$route['info/web'] = "articles/tags/internet-abroad";
$route['info/hotel'] = "articles/tags/hotel";
$route['articles/tags/(:any)'] = "articles/articles_by_tags/$1";
$route['articles/destination/(:any)'] = "articles/articles_by_destination/$1";
$route['articles/(:any)'] = "articles/show_article/$1";
You are re-routing one URI to another re-routed URI.
$route['info/cell'] = "articles/tags/cellphone";
$route['info/rent'] = "articles/tags/car-rental";
$route['info/web'] = "articles/tags/internet-abroad";
$route['info/hotel'] = "articles/tags/hotel";
$route['articles/tags/(:any)'] = "articles/articles_by_tags/$1";
You are supposed to route from a URI to a Controller/Method, not to another URI.
Just route them all directly to each corresponding Controller/Method...
$route['info/cell'] = "articles/articles_by_tags/cellphone";
$route['info/rent'] = "articles/articles_by_tags/car-rental";
$route['info/web'] = "articles/articles_by_tags/internet-abroad";
$route['info/hotel'] = "articles/articles_by_tags/hotel";
$route['articles/tags/(:any)'] = "articles/articles_by_tags/$1";
Routes Documentation

Pagination in CodeIgniter, need to disable query strings so we can cache

We have a CI installation that has the following setting in our config...
$config['enable_query_strings'] = TRUE;
We need this in order for another area of our application to run correctly with a third party API. What's happening, however, is that pagination is defaulting to a query string method of doing pagination, which doesn't play well with caching.
Right now, they look like this...
http://localhost/something/?&page=6
It's not playing well with caching, mainly because every page URL is the same page to CI. My goal is to get switched over to the below example without messing with global settings for the rest of my application.
I've been trying for hours to find a way to disable the above setting only within this single part of the application, so that we can properly have separate URLs for the pagination, like this...
http://localhost/something/1
http://localhost/something/2
http://localhost/something/3
So far, I have been unable to overide that setting for this controller, and honestly, I'm not sure there's even a way to actually do it. Any help is appreciated. There's got to be some method of disabling a feature for a single controller somehow.
Could you use routing?
$route['something/page/(:num)'] = "something?&page=$1";
edit: to turn off pagination query strings with $config['enable_query_strings'] = TRUE;
system/libraries/Pagination.php
~line 134
change
if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
{
if ($CI->input->get($this->query_string_segment) != 0)
{
$this->cur_page = $CI->input->get($this->query_string_segment);
// Prep the current page - no funny business!
$this->cur_page = (int) $this->cur_page;
}
}
else
{
if ($CI->uri->segment($this->uri_segment) != 0)
{
$this->cur_page = $CI->uri->segment($this->uri_segment);
// Prep the current page - no funny business!
$this->cur_page = (int) $this->cur_page;
}
}
to
if ($CI->uri->segment($this->uri_segment) != 0)
{
$this->cur_page = $CI->uri->segment($this->uri_segment);
// Prep the current page - no funny business!
$this->cur_page = (int) $this->cur_page;
}
~line 196
if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
{
$this->base_url = rtrim($this->base_url).'&'.$this->query_string_segment.'=';
}
else
{
$this->base_url = rtrim($this->base_url, '/') .'/';
}
to
$this->base_url = rtrim($this->base_url, '/') .'/';
that might do it. Or maybe better form would be to hook into the page...
Simple solution...
$this->config->set_item('enable_query_strings',FALSE);
Just put this before you call your pagination logic in the controller. Thanks go to Taftse in the #codeigniter IRC channel for this simple override.

Resources