i have developed an Apache link module in Delphi, which also contains an upload function via a WebActionItem(Multipart form data).
The upload also works correctly as long as the client does not cancel the request.
However, if the request is aborted, the memory of the httpd.exe will increase continuously.
Within a few seconds the memory reaches the maximum 8 GB and the child-process of Apache is killed.
The strange thing is that my upload function is not reached at all if a request get canceled by the client.
Only the initialization of the WebModule is called when a request comes in.
My questions:
Does Apache take care of the upload of the file and passes it to the Delphi WebModule?
How can I intervene if my upload function in the WebModule is not called at all when a request is aborted by the client?
I am very grateful for any hints, because I'm looking for a solution since hours.
Edit:
Example for dpr-File:
library mod_restserver;
uses
{$IFDEF MSWINDOWS}
Winapi.ActiveX,
System.Win.ComObj,
{$ENDIF }
Web.WebBroker,
Web.ApacheApp,
Web.HTTPD24Impl,
Data.DBXCommon,
Datasnap.DSSession,
RESTServer.Service.WebModules in 'RESTServer.Service.WebModules.pas' {webModul: TWebModule};
// httpd.conf-Einträge:
//
(*
LoadModule webbroker_module modules/mod_restserver.dll
<Location /rest>
SetHandler mod_restserver-handler
</Location>
*)
//
// Diese Einträge setzen voraus, dass das Ausgabeverzeichnis für dieses Projekt das apache/modules-Verzeichnis ist.
//
// httpd.conf-Einträge sollten unterschiedlich sein, wenn das Projekt auf eine der folgenden Weisen geändert wird:
// 1. Der Name der Variable TApacheModuleData wird geändert.
// 2. Das Projekt wird umbenannt.
// 3. Das Ausgabeverzeichnis ist nicht das Verzeichnis apache/modules.
// 4. Die Erweiterung der dynamischen Bibliothek ist von der Plattform abhängig. Verwenden Sie für Windows .dll und für Linux .so.
//
// Exportierte Variable deklarieren, damit Apache auf dieses Modul zugreifen kann.
var
GModuleData: TApacheModuleData;
exports
GModuleData name 'webbroker_module';
procedure TerminateThreads;
begin
TDSSessionManager.Instance.Free;
Data.DBXCommon.TDBXScheduler.Instance.Free;
end;
begin
{$IFDEF MSWINDOWS}
CoInitFlags := COINIT_MULTITHREADED;
{$ENDIF}
Web.ApacheApp.InitApplication(#GModuleData);
Application.Initialize;
Application.WebModuleClass := WebModuleClass;
TApacheApplication(Application).OnTerminate := TerminateThreads;
Application.Run;
end.
And example for the webmodule:
unit RESTServer.Service.WebModules;
interface
uses
{$IFDEF MSWINDOWS}
Winapi.ActiveX,
System.Win.ComObj,
{$ENDIF }
System.SysUtils, System.Classes,
Web.HTTPApp, Web.WebFileDispatcher, Web.HTTPProd,
Datasnap.DSHTTPWebBroker, Datasnap.DSServer, DataSnap.DSAuth, Datasnap.DSCommonServer,
IPPeerServer, IdContext, Datasnap.DSHTTP, ReqMulti, JSON, System.IOUtils;
type
TwebModul = class(TWebModule)
dsServer: TDSServer;
procedure WebModule1DefaultHandlerAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
procedure webModulfileUploadAction(Sender: TObject; Request: TWebRequest;
Response: TWebResponse; var Handled: Boolean);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
WebModuleClass: TComponentClass = TwebModul;
implementation
{$R *.dfm}
uses
Web.WebReq, Datasnap.DSSession;
procedure TwebModul.WebModule1DefaultHandlerAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
Response.Content :=
'{"return":-1, "result":0, "msg":"ressource unknown"}';
end;
procedure TwebModul.webModulfileUploadAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
joResponse: TJSONObject;
iCount,
iReturn, iResult: Integer;
sPath, s: String;
aFile: TAbstractWebRequestFile;
ms: TMemoryStream;
begin
joResponse := TJSONObject.Create;
iReturn := 0;
iResult := 0;
try
try
if Request.Files.Count > 0 then
begin
for iCount := 0 to Request.Files.Count - 1 do
begin
aFile := Request.Files.Items[iCount];
ms := TMemoryStream.Create;
try
sPath := 'C:\Data\test.txt';
//if not DirectoryExists(sPath) then
// TDirectory.CreateDirectory(sPath);
aFile.Stream.Position := 0;
ms.CopyFrom(aFile.Stream, aFile.Stream.Size);
ms.SaveToFile(sPath);
finally
ms.free;
end;
Inc(iResult);
end;
end;
except
on E: Exception do
begin
s := E.Message;
iReturn := 2;
iResult := 0;
end;
end;
finally
joResponse.AddPair(TJSONPair.Create('return', TJSONNumber.Create(iReturn)));
joResponse.AddPair(TJSONPair.Create('result', TJSONNumber.Create(iResult)));
Response.ContentType := 'application/json; charset=utf-8';
Response.Content := joResponse.ToJSON;
end;
end;
initialization
CoInitialize(nil);
finalization
CoUninitialize;
end.
It happens that I have a database connection called Hana (Hana DB) with the programming language Go (Golang). Using the Iris framework.
What happens is that Go has problems with null data. You have to use special data types in the struct as (using the sql library that comes by default when installing Go) sql.NullString
The question is, I have a GetEmployeeData () function called when connecting to a certain URL and returning a JSON. The problem is that it does not return anything, a CONNECTION error REJECTED appears and in the console it prints an error:
hdb.protocol 2018/07/13 16:31:06 option.go:120: type code tcNull not implemented exit status 1
The code was already tested in another SQL call in another function and it works, but this SQL I suppose that when returning 1 only Null or more it gives error.
The code is the following:
func GetEmployeeData(ctx iris.Context) {
const (
driverName = "hdb"
hdbDsn = "hdb://SYSTEM:manager#62.28.253.218:30015"
)
//db, err := sql.Open(driverName, hdbDsn)
//Crea una abstraccion de conexion a base de datos pero no conecta
//Si no que prepara todo para la conexion
db, err := sql.Open(driverName, hdbDsn)
if err != nil {
log.Fatal(err)
}
//Declaramos variable de QUERY
//var peticion = GetCompanyData()
//fmt.Println(peticion)
// var companyData = GetCompanyData()
var request = `Select
"U_idcodigo",
"U_idapenom",
"U_idnumint",
"U_ctestado",
"U_idemail",
"U_cttipfun",
"U_uocodcar",
TO_CHAR("U_uocarasi",'dd/mm/yyyy'),
"U_uocodfun",
TO_CHAR("U_uofunasi",'dd/mm/yyyy'),
"U_idestciv",
"U_idsexo",
"U_idnacion",
"U_codcat",
"U_codesp",
TO_CHAR("U_idfecnac",'dd/mm/yyyy'),
"U_idfotogr",
"U_dodirecc","
U_docodpai",
"U_doregion",
"U_doprovin",
"U_docomuna",
"U_docodpos",
"U_donummov",
"U_cttipcon",
TO_CHAR("U_ctfecing",'dd/mm/yyyy'),
"U_uolugpag",
"U_uolugtra",
"U_uocodger",
"U_uocoddep",
"U_uocodsec",
"U_rpforpag",
"U_rpcodban",
"U_rpctacte",
"U_rptipocta",
"U_rpunisal",
"U_rpmoneda",
TO_VARCHAR("U_rpsalar"),
"U_tijor",
TO_VARCHAR("U_hdia"),
TO_VARCHAR("U_cthorcon"),
"U_sindi",
"U_jubil",
"U_turno",
TO_CHAR("U_turnoasi",'dd/mm/yyyy'),
"U_comentar"
FROM SBODemoCL."#A1A_MAFU"
Where "U_idcodigo" = '7579684-6'`
rows, err := db.Query(request)
if err != nil {
log.Fatal(err)
fmt.Println("No funciono la peticion")
}
defer rows.Close()
defer db.Close()
fmt.Println("Funciono la peticion")
type Employee struct {
CodigoEmpleado sql.NullString `json:"CodigoEmpleado"` //CODIGO UNICO DE EMPLEADO
Nombres sql.NullString `json:"Nombres"` //APELLIDO Y NOMBRE
NroInterno sql.NullString `json:"NroInterno"` //NUMERO INTERNO EN EMPRESA
Estado sql.NullString `json:"Estado"`
Email sql.NullString `json:"Email"` //CORREO ELECTRONICO
TipoF sql.NullString `json:"TipoF"` //TIPO DE FUNCIONARIO
Cargo sql.NullString `json:"Cargo"` //EL CARGO QUE OCUPA EL EMPLEADO
FechaCargo sql.NullString `json:"FechaCargo"` //FECHA DE ASIGNACION DE CARGO
Funcion sql.NullString `json:"Funcion"` //QUE FUNCION CUMPLE
FechaFuncion sql.NullString `json:"FechaFuncion"` //CUANDO SE LE ASIGNO SU FUNCION
Civil sql.NullString `json:"Civil"` //ESTADO CIVIL
Sexo sql.NullString `json:"Sexo"` //SI ES MASCULINO O FEMENINO
Nacionalidad sql.NullString `json:"Nacionalidad"` //SU NACIONALIDAD
Categoría sql.NullString `json:"Categoría"` //SU CATEGORIA
Especialidad sql.NullString `json:"Especialidad"` //SU ESPECIALIDAD
Nacimiento sql.NullString `json:"Nacimiento"` //FECHA DE NACIMIENTO
Fotografia sql.NullString `json:"Fotografia"` //RUTA DE MAPA DE BITS DE IMAGEN SOBRE EL EMPLEADO
Direccion sql.NullString `json:"Direccion"` //DIRECCION DE CASA DEL EMPLEADO
Pais sql.NullString `json:"Pais"` //PAIS EN DONDE SE ENCUENTRA ACTUALMENTE
Region sql.NullString `json:"Region"` //REGION DONDE SE ENCUENTRA ACTUALMENTE
Provincia sql.NullString `json:"Provincia"` //PROVINCIA DONDE SE ENCUENTRA ACTUALMENTE
Comuna sql.NullString `json:"Comuna"` //COMUNA DONDE SE ENCUENTRA ACTUALMENTE
C_Postal sql.NullString `json:"C_Postal"` //SU CODIGO POSTAL
Celular sql.NullString `json:"Celular"` //NUMERO DE CELULAR
TipoContrato sql.NullString `json:"TipoContrato"` //TIPO DE CONTRATO
FechaIngreso sql.NullString `json:"FechaIngreso"` //FECHA DE INGRESO A LA COMPAÑIA
LugarPago sql.NullString `json:"LugarPago"` //LUGAR DONDE NORMALMENTE COBRA EL EMPLEADO
LugarTrabajo sql.NullString `json:"LugarTrabajo"` //LUGAR DONDE NORMALMENTE TRABAJA EL EMPLEADO
Gerencia sql.NullString `json:"Gerencia"` //¿Quien es su genente? No es claro
Departamento sql.NullString `json:"Departamento"` //¿Si tiene departamento? ¿O la ubicacion de su departamento? ¿O con departamento se refieren a su partido o barrio?
Seccion sql.NullString `json:"Seccion"` //¿? Tampoco me queda claro
FormaPago sql.NullString `json:"FormaPago"` //COMO SE LE PAGA NORMALMENTE AL EMPLEADO
Banco sql.NullString `json:"Banco"` //EL BANCO QUE SE UTILIZA PARA DEPOSITAR EL SALARIO DEL EMPLEADO
CuentaBanco sql.NullString `json:"CuentaBanco"` //CUENTA BANCARIO DONDE SE DEPOSITA EL SALARIO
UnidadSalarial sql.NullString `json:"UnidadSalarial"` //¿? Su unidad salarial
Moneda sql.NullString `json:"Moneda"` //CON QUE TIPO DE MONEDA SE DEPOSITA SU SUELDO (EUROS, DOLARES, PESOS, ETC...)
Sueldo sql.NullString `json:"Sueldo"` //SUELDO BASICO DEL EMPLEADO
TipoJornada sql.NullString `json:"TipoJornada"` //TIPO DE JORNADA DEL EMPLEADO (CANTIDAD DE HORAS QUE TRABAJA)
HorasDia sql.NullString `json:"HorasDia"` //HORAS DIARIAS QUE ESTIPULA EL CONTRATO
HorasMes sql.NullString `json:"HorasMes"` //HORAS MENSUALES QUE ESTIPULA EL CONTRATO
Sindicato sql.NullString `json:"Sindicato"` //SINDICATO AL QUE PERTENECE EL EMPLEADO
Jubilido sql.NullString `json:"Jubilido"` //¿? Puede ser si es que esta jubilado o no
Turno sql.NullString `json:"Turno"` //¿Turno de que?
FechaTurno sql.NullString `json:"FechaTurno"` //FECHA EN QUE SE LE ASIGNO EL TURNO
Comentarios sql.NullString `json:"Comentarios"` //Comentarios sobre el empleado
}
// numero := 0
//
// ac := accounting.Accounting{
// Symbol: "", //El símbolo
// Precision: 2, // ¿Cuántos "centavos" queremos? (también llamado precisión)
// Thousand: companyData["ISeparator"], //Separador de miles
// Decimal: companyData["FSeparator"], //Separador de decimales
// }
employ := new(Employee)
for rows.Next() {
err := rows.Scan(
&employ.CodigoEmpleado,
&employ.Nombres,
&employ.NroInterno,
&employ.Estado,
&employ.Email,
&employ.TipoF,
&employ.Cargo,
&employ.FechaCargo,
&employ.Funcion,
&employ.FechaFuncion,
&employ.Civil,
&employ.Sexo,
&employ.Nacionalidad,
&employ.Categoría,
&employ.Especialidad,
&employ.Nacimiento,
&employ.Fotografia,
&employ.Direccion,
&employ.Pais,
&employ.Region,
&employ.Provincia,
&employ.Comuna,
&employ.C_Postal,
&employ.Celular,
&employ.TipoContrato,
&employ.FechaIngreso,
&employ.LugarPago,
&employ.LugarTrabajo,
&employ.Gerencia,
&employ.Departamento,
&employ.Seccion,
&employ.FormaPago,
&employ.Banco,
&employ.CuentaBanco,
&employ.UnidadSalarial,
&employ.Moneda,
&employ.Sueldo,
&employ.TipoJornada,
&employ.HorasDia,
&employ.HorasMes,
&employ.Sindicato,
&employ.Jubilido,
&employ.Turno,
&employ.FechaTurno,
&employ.Comentarios,
)
if err != nil {
log.Fatal(err)
}
// f, err := strconv.ParseFloat(valor6, 64)
// salario := ac.FormatMoney(f)
}
err = rows.Err()
if err != nil {
log.Fatal(err)
fmt.Println("Ocurrio un error")
}
ctx.JSON(employ)
}
The libraries that are imported are the following:
import (
"database/sql"
"fmt"
"log"
"strconv"
"github.com/kataras/iris"
"github.com/leekchan/accounting"
// Register hdb driver.
_ "github.com/SAP/go-hdb/driver"
)
The error calls an option.go file. All the code of option go is the following:
/*
Copyright 2014 SAP SE
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package protocol
import (
"fmt"
"github.com/SAP/go-hdb/internal/bufio"
)
type booleanType bool
func (t booleanType) String() string {
return fmt.Sprintf("%t", t)
}
type intType int32
func (t intType) String() string {
return fmt.Sprintf("%d", t)
}
type bigintType int64
func (t bigintType) String() string {
return fmt.Sprintf("%d", t)
}
type doubleType float64
func (t doubleType) String() string {
return fmt.Sprintf("%g", t)
}
type stringType []byte
type binaryStringType []byte
func (t binaryStringType) String() string {
return fmt.Sprintf("%v", []byte(t))
}
//multi line options (number of lines in part header argumentCount)
type multiLineOptions []plainOptions
func (o multiLineOptions) size() int {
size := 0
for _, m := range o {
size += m.size()
}
return size
}
//pointer: append multiLineOptions itself
func (o *multiLineOptions) read(rd *bufio.Reader, lineCnt int) {
for i := 0; i < lineCnt; i++ {
m := plainOptions{}
cnt := rd.ReadInt16()
m.read(rd, int(cnt))
*o = append(*o, m)
}
}
func (o multiLineOptions) write(wr *bufio.Writer) {
for _, m := range o {
wr.WriteInt16(int16(len(m)))
m.write(wr)
}
}
type plainOptions map[int8]interface{}
func (o plainOptions) size() int {
size := 2 * len(o) //option + type
for _, v := range o {
switch v := v.(type) {
default:
outLogger.Fatalf("type %T not implemented", v)
case booleanType:
size++
case intType:
size += 4
case bigintType:
size += 8
case doubleType:
size += 8
case stringType:
size += (2 + len(v)) //length int16 + string length
case binaryStringType:
size += (2 + len(v)) //length int16 + string length
}
}
return size
}
func (o plainOptions) read(rd *bufio.Reader, cnt int) {
for i := 0; i < cnt; i++ {
k := rd.ReadInt8()
tc := rd.ReadB()
switch TypeCode(tc) {
default:
outLogger.Fatalf("type code %s not implemented", TypeCode(tc))
case tcBoolean:
o[k] = booleanType(rd.ReadBool())
case tcInteger:
o[k] = intType(rd.ReadInt32())
case tcBigint:
o[k] = bigintType(rd.ReadInt64())
case tcDouble:
o[k] = doubleType(rd.ReadFloat64())
case tcString:
size := rd.ReadInt16()
v := make([]byte, size)
rd.ReadFull(v)
o[k] = stringType(v)
case tcBstring:
size := rd.ReadInt16()
v := make([]byte, size)
rd.ReadFull(v)
o[k] = binaryStringType(v)
}
}
}
func (o plainOptions) write(wr *bufio.Writer) {
for k, v := range o {
wr.WriteInt8(k)
switch v := v.(type) {
default:
outLogger.Fatalf("type %T not implemented", v)
case booleanType:
wr.WriteInt8(int8(tcBoolean))
wr.WriteBool(bool(v))
case intType:
wr.WriteInt8(int8(tcInteger))
wr.WriteInt32(int32(v))
case bigintType:
wr.WriteInt8(int8(tcBigint))
wr.WriteInt64(int64(v))
case doubleType:
wr.WriteInt8(int8(tcDouble))
wr.WriteFloat64(float64(v))
case stringType:
wr.WriteInt8(int8(tcString))
wr.WriteInt16(int16(len(v)))
wr.Write(v)
case binaryStringType:
wr.WriteInt8(int8(tcBstring))
wr.WriteInt16(int16(len(v)))
wr.Write(v)
}
}
}
If someone wants to download the library in their Go folder this is the command:
go get github.com/SAP/go-hdb/driver
This is your Github link: https://github.com/SAP/go-hdb
Does anyone know how to fix the error?
Your error is complaining "I don't know how to read a null value."
The options.go file's read function has a switch statement at line 117 that implements the ways to read various database types. You will need to update this switch statement to be able to handle a null ("tcNull"?) type value.
The markdown:
| Symbol | Beschreibung |
|--------|--------------|
| ![Erfolgskriterium erfüllt](/assets/reports/audit/signal_ok.jpg) | Wenn ein Erfolgskriterium erfüllt ist, so wurden bei den Tests alle gefundenen Fälle richtig umgesetzt gefunden. Keine weiteren Massnahmen sind nötig. |
| ![Erfolgskriterium nicht erfüllt](/assets/reports/audit/signal_not_ok.jpg) | Wenn ein Erfolgskriterium nicht erfüllt ist, so wurden bei den Tests Fälle gefunden, die das Kriterium nicht in der verlangten Art und Weise erfüllen. Beispiele für Probleme werden aufgeführt. Nötige Massnahmen werden aufgeführt oder es wird zu weiterführenden Quellen verwiesen. |
Result:
<table style="width:33%;">
<caption>Bewertungen und Symbole</caption>
<colgroup>
<col width="12%">
<col width="20%">
</colgroup>
<thead>
...
I'd like to have a table with auto width by default. How can this be achieved?
From the Pandoc README on pipe tables:
If a pipe table contains a row whose printable content is wider than the column width (see --columns), then the cell contents will wrap, with the relative cell widths determined by the widths of the separator lines.
The idea of markdown is to make it look nice in the source as well, for example with multiline tables you can control the column widths as well:
---------------------------------------------------------------
Symbol Beschreibung
------ ---------------
![Erfolgskriterium Wenn ein Erfolgskriterium erfüllt
erfüllt][ok] ist, so wurden bei den Tests alle
gefundenen Fälle richtig umgesetzt
efunden. Keine weiteren Massnahmen
sind nötig.
![Erfolgskriterium Wenn ein Erfolgskriterium nicht
nicht erfüllt][not_ok] erfüllt ist, so wurden bei den Tests
Fälle gefunden, die das Kriterium
nicht in der verlangten Art und Weise
erfüllen. Beispiele für Probleme
werden aufgeführt. Nötige Massnahmen
werden aufgeführt oder es wird zu
weiterführenden Quellen verwiesen.
---------------------------------------------------------------
[ok]: /assets/reports/audit/signal_ok.jpg
[not_ok]: /assets/reports/audit/signal_not_ok.jpg
If you really, really don't want column widths, you'd have to use simple tables, but they don't allow multiline text. Or write a pandoc filter to remove the widths.
I'd like to have a table with auto width by default. How can this be achieved?
Increase the widths of the separator lines between the header row and content rows.
Pandoc Manual: pipe_tables section only briefly mentions how the table separator lines affect relative column widths.
If a pipe table contains a row whose printable content is wider than the column width (see --columns), then the cell contents will wrap, with the relative cell widths determined by the widths of the separator lines.
Experimentally, one can find that the widths of the separator lines also affects the overall table width.
In my case (pandoc 1.19.1), the following markdown has the overall separator line widths increased from the question example above …
| Symbol | Beschreibung |
|----------------------|------------------------------------------------------------------|
| ![Erfolgskriterium erfüllt](/assets/reports/audit/signal_ok.jpg) | Wenn ein Erfolgskriterium erfüllt ist, so wurden bei den Tests alle gefundenen Fälle richtig umgesetzt gefunden. Keine weiteren Massnahmen sind nötig. |
| ![Erfolgskriterium nicht erfüllt](/assets/reports/audit/signal_not_ok.jpg) | Wenn ein Erfolgskriterium nicht erfüllt ist, so wurden bei den Tests Fälle gefunden, die das Kriterium nicht in der verlangten Art und Weise erfüllen. Beispiele für Probleme werden aufgeführt. Nötige Massnahmen werden aufgeführt oder es wird zu weiterführenden Quellen verwiesen. |
… generates the following html table…
<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 74%" />
</colgroup>
<thead>
<tr class="header">
<th>Symbol</th>
<th>Beschreibung</th>
</tr>
… which has no width contraint on the table itself.
The resulting table, in this case, spans the window. And, the column content reflows nicely as the window width changes.
You might hate me. But why not removing the <colgroup> using javascript?
Its not really the clean way but before you force yourself to change the table style, this might have other side effects that you dont want, using this easy solution will also work.
And it wont *ck up your markdown with heavy table syntax.
Just apply some more CSS to overwrite current CSS.
pandoc "--variable=include-before:<style>body > table > colgroup > col { width: unset!important }</style>"
This will insert one more line directly after html body-tag inside the output document, which selects all body > table > colgroup > col elements and overwrite their width setting.
I am trying to change my app language without restarting the app. I have checked all the example and asked questions on the stack overflow. But i didn't find any link helpful.
I am using the following code.
- (void)languageChanger {
MBProgressHUD * hudFirst = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hudFirst.delegate = self;
hudFirst.labelText=NSLocalizedString(#"Please wait", #"Message");
hudFirst.center=self.view.center;
hudFirst.dimBackground=YES;
[hudFirst show:YES];
//[self localizedString:#"pl"];
NSString *Language=_select.titleLabel.text;
if ([Language isEqualToString:[languageArray objectAtIndex:0]]|| Language == nil) {
Language=#"en";
}
else{
Language=#"pl";
}
[self localizedString:Language];
NSString *uid = [[NSUserDefaults standardUserDefaults] objectForKey:#"userId"];
NSDictionary *inputDic=[NSDictionary dictionaryWithObjectsAndKeys:Language,#"lang",uid,#"id", nil];
NSString *urlString=[Globals urlCombileHash:kApiDominStage ClassUrl:#"ChangeLanguage/" apiKey:[Globals apiKey]];
[Globals PostApiURL:urlString data:inputDic success:^(id responseObject) {
[self localizedString:Language];
[hudFirst hide:YES];
}
failure:^(NSError *error) {
[hudFirst hide:YES];
_errorView.hidden=NO;
_lblMessage.text=NSLocalizedString(#"Sorry! Internal Server Error.", #"Message");
blurredView.hidden=NO;
}];
}
- (void) localizedString:(NSString *)key {
NSString *langCode = key;
NSArray *languages = nil;
languages = [NSArray arrayWithObject:langCode];
[[NSUserDefaults standardUserDefaults] setObject:languages forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
You need to create .strings file for every language.
For this, got to Project->localizations->create new file by pressing plus buttonenter image description here
In this .strings file enter your keys like this->
I've done for spanish.
/*
French.strings
EzEve
Created by MOHIT MATHUR on 07/12/15.
Copyright © 2015 CGT. All rights reserved.
*/
"Old_Password"="Introduzca su contraseña antigua";
"New_Password"="Introduzca su nueva contraseña";
"Confirm_Password"="Introduzca su nueva contraseña";
"Password_Length"="La contraseña debe tener al menos 6 caracteres";
"Password_Match"="Nueva contraseña y Confirmar contraseña no coinciden!";
"Camera_Support"="Este dispositivo no es compatible con la cámara";
"Country_Code"="Por favor, introduzca el código de país";
"Phone_Length"="Número de teléfono debe tener una antigüedad de 7 dígitos";
"Email_Validation"="Por favor, introduzca la dirección de correo electrónico válida (abc#example.com)";
"Email_Phone"="Número de teléfono debe ser por lo menos entrar en correo electrónico o número de teléfono";
"Fetch_Countries"="Imposible obtener países. Comprueba tu conexión a Internet y oprima REINT para volver a intentarlo o CANCELAR para abortar";
"Internet_Connection"="Conexión a Internet parece estar fuera de línea!";
"Profile_Change"="Perfil actualizado correctamente";
"Password_Change"="Contraseña cambiada con éxito";
"Name"="Nombre";
"Surname"="Apellido";
"UserName"="Nombre de usuario";
"Email"="Dirección de correo electrónico";
"Code"="1 (EE.UU.)";
"Phone"="Número de teléfono";
"Address"="Dirección";
"City"="Ciudad";
"State"="Estado";
"Zipcode"="Código postal";
"Country"="País";
"OldPassword"="Contraseña anterior";
"NewPassword"="Nueva contraseña";
"ConfirmPassword"="Confirmar contraseña";
"Change Password"="Cambiar la contraseña";
"Profile"="Configuración del perfil";
"Save"="Ahorrar";
"Avatar"="Seleccione Avatar";
"Male"="Masculino";
"Female"="Hembra";
"<20"="<20 años";
"20 and 30"="Entre el 20 y 30";
"30 and 39"="Entre 30 y 39";
"40 and 49"="Entre el 40 y el 49";
"50 and 59"="Entre el 50 y el 59 ";
"60 and 69"="Entre el 60 y el 69";
">70 Years"="> 70 años";
"Age"="Grupo de Edad";
"Done"="Hecho";
"Cancel"="Cancelar";
"AgeGroup"="Seleccione Grupo de Edad";
"Device"="Mi dispositivo";
"Facebook"="Tu Facebook";
"Twitter"="Tu Twitter";
Now, create a common method that can be accessible from all classes->
+ (NSString*)setLanguage:(NSString *)key{
NSMutableDictionary *dict=[[NSMutableDictionary alloc]initWithDictionary:[[NSUserDefaults standardUserDefaults]objectForKey:KEY_USER_INFO]];
return NSLocalizedStringFromTable(key, [dict objectForKey:KEY_LANGUAGE], #"");
}
Now, call this method wherever you need to set the text->
[CommonFunctions setLanguage:#"Facebook"];
The CodeAnalysis return Unable to find one or more indirectly-referenced assemblies. These assemblies are not required for the analysis. However, without these assemblies, the analysis results could be incomplete.
But I can't find which assembly is not found. I tried to set MSbuild log in verbose but there is no more informations (see the log below).
Have you an idea to find this assemblies?
Sorry, it's in french :
Tâche "CodeAnalysis"
6> Analyse du code en cours...
6>
6> Outils de ligne de commande Microsoft (R) FxCop, version 12.0 (12.0.21005.1) X86
6> Copyright (C) Microsoft Corporation, Tous droits réservés.
6>
6> dataflowrules.dll chargé...
6> designrules.dll chargé...
6> globalizationrules.dll chargé...
6> interoperabilityrules.dll chargé...
6> maintainabilityrules.dll chargé...
6> mobilityrules.dll chargé...
6> namingrules.dll chargé...
6> performancerules.dll chargé...
6> portabilityrules.dll chargé...
6> reliabilityrules.dll chargé...
6> securityrules.dll chargé...
6> securitytransparencyrules.dll chargé...
6> usagerules.dll chargé...
6> Addins.dll chargé...
6> Initialisation du moteur Introspection en cours...
6> Analyse en cours...
6> Initialisation du moteur Phoenix en cours...
6> Analyse en cours...
6> Analyse terminée.
6>
6> REMARQUE : impossible de trouver un ou plusieurs assemblys référencés. Utilisez le commutateur '/directory' ou '/reference' pour spécifier des chemins de recherche de références d'assembly complémentaires.
6>
6>
6> Écriture du rapport dans D:\..\Addins.dll.CodeAnalysisLog.xml...
6> Terminé :00:00:13.3407584
6> Impossible de trouver un ou plusieurs des assemblys référencés indirectement. Ces assemblys ne sont pas requis pour l'analyse. Toutefois, sans ces assemblys, les résultats d'analyse pourraient être incomplets.
6> Analyse du code terminée -- 0 erreur(s), 0 avertissement(s)
I had the same problem. Run FxCopCmd from the command in order to see what the problem is:
c:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\FxCop\FxCopCmd.exe /f:YourDLL.dll /console /verbose > problem.txt
Scan the output for "One or more referenced" and the assemblies that it had problems with are listed just below that.