entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

2votos

Problema con Route en CodeIgniter

Hola, estoy programando un sitio web con CodeIgniter y implementé la opción de agregar idiomas y quiero que el sitio sea en varios idiomas, ya tengo implementado la lógica y funciona bien con el route que hice pero es a mano y quiero hacerlo que funcione para cualquier idioma sin yo tener que modificar ningún código:
Mi route actualmente:

$route['en'] = "content/home";
$route['es'] = "content/home";
$route['rs'] = "content/home";
$route['en/(:any)/listar'] = "content/listar";
$route['en/(:any)/(:any)'] = "content/ver"; 
$route['es/(:any)/listar'] = "content/listar";
$route['es/(:any)/(:any)'] = "content/ver"; 
$route['rs/(:any)/listar'] = "content/listar";
$route['rs/(:any)/(:any)'] = "content/ver"; 

las siglas en,es y rs son las abreviaturas de los idiomas que serían english, español y ruso. quiero que mi sitio sea lo más genérico posible con el fin de convertirlo en un CMS en un futuro no muy lejano.
Aquí el código de prueba:
el Código de mi index en el Controllador es este:

===================================
public function home(){/*   
    ======================  
    = Home del Sitio Web =
    ======================      
        */  
        $idioma = $this->uri->segment(1);        
        $this->load->model(array('session_model','noticias_model'));        
        $data['idioma'] = $idioma;          
        $data['idiomas'] = get_idiomas();       
        $data['secciones_existentes'] = $this->session_model->get_seccion_activas($idioma);             
        $this->load->view('head');
        $this->load->view('home',$data);
        $this->load->view('foot');
    }

el código de mi view en home es:
========================

<body>
  <div class="container">
    <?php 
      foreach ($idiomas as $__idioma__) {        
        echo '<a href="'.base_url().$__idioma__->abre.'">'.$__idioma__->nombre.'</a>   '; 
      }
     ?>
    <h2>Secciones Activas</h2>   
    <table class="table">
      <tr>
        <th>Nombre a Mostrar</th>
        <th>Url del Icono</th>                
        <th>Idioma</th> 
      </tr>
      <?php         
        foreach ($secciones_existentes->result() as $seccionActiva) {
        ?>
        <tr>
          <td><a href="<?php echo  '/'.$idioma.'/'.get_uri($seccionActiva->nombre_mostrar).'/listar';?>" title=""><?php echo $seccionActiva->nombre_mostrar;?></a></td>
          <td><?php echo $seccionActiva->url_icono;?></td>
          <td><?php echo $seccionActiva->idioma;?></td>
        <?php }?>
        </tr>
  </table> 
  <h2>TimeLine</h2>
  <div id="timeline">
  <?php         
      $timeline = get_TimeLine($idioma); 
      foreach ($timeline as $_tnews) {
      ?>
      <div class="content_timeline">
      <img src="<?php echo $_tnews->foto_portada;?>" alt="">
      <div>
          <span><p class="seccion"><?php echo $_tnews->seccion_nombre;?></p>
                <p class="tiempo"><?php echo ago($_tnews->momento_publicada, ''); ?></p></span>               
          <a href="<?php echo  '/'.$idioma.'/'.get_uri($_tnews->seccion_nombre).'/'.$_tnews->url_noticia;?>" title=""> <h4><?php echo $_tnews->titulo_noticia;?></h4></a>                        
      </div>

      </div>        
  <?php } ?>
  </div>          
  <p class="footer">Page rendered in <strong>{elapsed_time}</strong> seconds</p>
  </div>
</body>

Como verás es una prueva lo que hago aquí, es solamente para probar como va funcionando lo que estoy programando. Saludos Dairon
Aquí un PrintScreen. las secciones Activas no tiene actualizado el código así que no carga nada ;) y le queité el ruso:
PrintScreen:
=========

PrintScreen del Home

Saludos Atentamente Dairon.

0voto

white comentado

Hola @dairon, antes de ver como hacerlo dinamico podrías decir como manejas los idiomas en tu controlador? hay varios metodos

  • usar _remap() para el controlador y tener una lista de idiomas definida.
  • usar hooks
  • tener un Controlador base MY_lang.php

https://ellislab.com/codeigniter/user-guide/general/controllers.html#Remapping
https://github.com/bcit-ci/CodeIgniter/wiki/CodeIgniter-2.1-internationalization-i18n

0voto

dairon comentado

Aún no he entrado en detalles en el idioma del Frontend pues aún no he terminado el BackEnd, pero hasta ahora lo que hago es levantar el timeline en el cual me ayudaste hace un tiempo @white para cada idioma pero tengo que agregarlo como lo puse arriba

0voto

dairon comentado

@white mano edité mi pregunta y agregué el código y un PrintScreen.
Saludos

1 Respuesta

1voto

white Puntos75880

Te dejo un metodo en esta respuesta.

Primero Necesitas extender CI_Controller en caso de que aun no lo extiendas, esto permite que todos los controladores hereden de este, asi les pasamos datos de configuracion a todos.

application/core/MY_Controller.php:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class MY_Controller extends CI_Controller{

    protected $language = null;

    function __construct()
    {
        parent::__construct();

        // load url helper
        $this->load->helper('url');

        // get language from url
        $lang_code = $this->uri->segment(1);

        // revizamos si se definio el lenguaje desde la url
        if( isset($lang_code) )
        {
            // verificamos si el lenguaje esta definido en configuracion
            if( in_array($lang_code, array_keys($this->config->item('languages_list'))) )
                $this->language = $this->config->item('languages_list')[$lang_code];

            // en caso de no existir el lenguaje mostramos un 404
            else
                return show_404();
        }

        // en caso de no estar definido el lenguaje cargamos el predeterminado
        else
        {
            $default_language = $this->config->item('language');
            $this->language = $this->config->item('language');
        }
    }
}

En este controlador obtenemos el codigo del lenguaje desde la url y verificamos que este definido, si el lenguaje no existe mostramos un 404, si no esta presente en la url mostramos el predeterminado.

con este controlador obtienes el lenguaje en todos tus controladores

tusitio.net/es/login
tusitio.net/es/home
tusitio.net/es/register

etc...


Ahora edita tu config.php y agrega esto al final:

/*
| Lenguajes disponibles
*/
$config['languages_list'] = array(
    'es' => 'spanish',
    'en' => 'english',
    'fr' => 'french'
);

esto define que lenguajes estan disponibles en tu sitio.


en el archivo application/config/routes.php agrega esto:

$route['^([a-z]{2})/(.+)$'] = '$2';

con esta ruta capturamos el codigo del lenguaje desde la url.


en la raiz de tu sitio no olvides que tu .htaccess debe contener esto:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteRule ^(.*)$ index.php/$1 [L]

Ahora en tus controladores extiende MY_Controller

<?php

    class MiControlador extends MY_Controller

obtienes el lenguaje con el campo $this->language de esta forma:

public function __construct()
{
    parent::__construct();
}

public function index()
{
    echo $this->language; // <----- obteniendo el lenguaje
    $this->load->view('welcome_message');
}

recuerda que una buena practica es escribir todas las variables en los archivos de idioma de codeigniter

application/language/english/home.php
application/language/spanish/home.php

es decir en lugar de

<h2>Secciones Activas</h2>

deberia ser:

<h2><?php echo lang('active_sections'); ?></h2>   

application/language/spanish/home.php:

<?php
    $lang['active_sections'] = 'Secciones activas';

saludos!

0voto

dairon comentado

existe alguna forma de hacer que el config.php se edite sin entrar en el, es que quiero hacerlo un cms y los usuiaros finales no deben tocar el código ??

0voto

white comentado

Que tal si agregas esa lista a la base de datos? la tabla podria ser:

lenguages

CREATE TABLE `languages` (
  `ID` INT NOT NULL AUTO_INCREMENT,
  `code` VARCHAR(4) NULL,
  `name` VARCHAR(45) NULL,
  PRIMARY KEY (`ID`),
  UNIQUE INDEX `code_UNIQUE` (`code` ASC));

ID  |  code  |  name
 1  |   es   |  spanish
 2  |   en   |  english

el controlador podria tener esto:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class MY_Controller extends CI_Controller{

    protected $language = null;

    function __construct()
    {
        parent::__construct();

        // load url helper
        $this->load->helper('url');

        $this->load->database();

        $query = $this->db->query('SELECT code, name FROM languages');

        $languages_list = array();

        foreach ($query->result_array() as $row) {
            $languages_list[$row['code']] = $row['name'];
        }

        // get language from url
        $lang_code = $this->uri->segment(1);

        // revizamos si se definio el lenguaje desde la url
        if( isset($lang_code) )
        {
            // verificamos si el lenguaje esta definido en configuracion
            if( in_array($lang_code, array_keys($languages_list)) )
                $this->language = $languages_list[$lang_code];

            // en caso de no existir el lenguaje mostramos un 404
            else
                return show_404();
        }

        // en caso de no estar definido el lenguaje cargamos el predeterminado
        else
        {
            $this->language = $this->config->item('language');
        }
    }
}

0voto

dairon comentado

mano yo tengo una tabla en mi base de datos que guarda el nombre,abreviatura,icono de los idiomas pero en el fonrtend los cargo de una copia echa a esa tabla que la tengo en un fichero en json de la misma tabla como respaldo o cache para el frontend del sitio.
Contenido de mi fichero idiomas.json::

[{"icono":"","abre":"es","nombre":"Espa\u00f1ol","id":"1"},{"icono":"","abre":"en","nombre":"English","id":"2"}]

este es mi fichero idiomas.json desde donde carga el método helper que llamó en el código de mi controller get_idiomas(); que es una llamada al fichero y luego le hago el json_decode();

0voto

dairon comentado

mano yo tengo una tabla en mi base de datos que guarda el nombre,abreviatura,icono de los idiomas pero las cargo ahi de una copia a esa tabla que la tengo en un fichero en json de la misma tabla como respaldo o cache para el frontend del sitio

0voto

white comentado

No entiendo bien lo que me dices, obtienes los idiomas desde una base de datos y lo guardas en un json? Para entenderte mejor podrias agregar el codigo de get_idiomas() ?

0voto

dairon comentado

Código de Get_idiomas:

function get_idiomas(){
    return _read("/idiomas.dbjson");
}

Código de _read:

function _read($path){
    #lee el fichero dado un camino y devuelve el objeto json
    $file = @fopen($path, 'r');
    $content = '';          
    if($file){  
        while(!feof($file)) {  
            $content .= fgets($file, 4096);              
        } 
        fclose($file);           
        return json_decode($content);
    }    
}

este es mi código de lectura de idioma:
contenido de idiomas.dbjson

[{"icono":"","abre":"es","nombre":"Espa\u00f1ol","id":"1"},{"icono":"","abre":"en","nombre":"English","id":"2"}]

0voto

white comentado

el metodo sería de la misma forma:

intenta asi:

$languages_json = get_idiomas();
$languages_list = array();

foreach ($languages_json as $row)
{
    $languages_list[$row['abre']] = $row['nombre'];
}

// get language from url
$lang_code = $this->uri->segment(1);

0voto

dairon comentado

mano ahora por la tarde lo pruebo que ahora estoy terminando de implementar la desactivasión de un idioma en el sitio y es un método que involucra a casi todo el sitio ;)

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta