Page tree

Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added info about getSegment, importInInternal, ImportTmx

...

  • import new openTM2-TMs
  • delete openTM2-TMs
  • create new empty openTM2-TM
  • import TMX
  • open TM and close TM: not possible see extra section in this document. Maybe we need trigger to flush tm to the disk, but also it could be done in some specific cases...
  • query TM for Matches: one query per TM, not quering multiple TMs at once.
  • query TM for concordance search
  • extract segment by it's location
  • save new entry to TM
  • delete entry from TM
  • localy clone TM
  • reorganize TM
  • get some statistics about service
  • also you can use tagreplacement endpoint to test tag replacement mechanism

...

Endpoints overview

default endpoint/example

Is async?

1Get the list of TMsReturns JSON list of TMsGET/%service%//t5memory/
2Create TM

Creates TM with the provided name

POST/%service%//t5memory/
3Create/Import TM in internal formatImport and unpack base64 encoded archive of .TMD, .TMI, .MEM files. Rename it to provided namePOST/%service%//t5memory/
4Clone TM LocalyMakes clone of existing tmPOST/%service%/%tm_name%/clone/t5memory/my+TM/clone
(+is placeholder for whitespace in tm name, so there should be 'my TM.TMD' and 'my TM.TMI'(and in pre 0.5.x 'my TM.MEM' also) files on the disk )
tm name IS case sensetive in url

5Reorganize TMReorganizing tm(replacing tm with new one and reimporting segments from tmd) - asyncGET/%service%/%tm_name%/reorganize/t5memory/my+other_tm/reorganize+ in 0.5.x and up
5Delete TMDeletes .TMD, .TMI files DELETE/%service%/%tm_name%//t5memory/%tm_name%/
6Import TMX into TMImport provided base64 encoded TMX file into TM - asyncPOST/%service%/%tm_name%/import/t5memory/%tm_name%/import+
7Export TMX from TMCreates TMX from tm. Encoded in base64GET/%service%/%tm_name%//t5memory/%tm_name%/
8Export in Internal formatCreates and exports archive with .TMD, .TMI files of TMGET/%service%/%tm_name%//t5memory/%tm_name%/status
9

Status of TM 

Returns status\import status of TMGET/%service%/%tm_name%/status/t5memory/%tm_name%/status
10Fuzzy searchReturns entries\translations with small differences from requestedPOST/%service%/%tm_name%/fuzzysearch/t5memory/%tm_name%/fuzzysearch
11Concordance searchReturns entries\translations that contain requested segmentPOST/%service%/%tm_name%/concordancesearch/t5memory/%tm_name%/concordancesearch
12Entry updateUpdates entry\translation POST/%service%/%tm_name%/entry/t5memory/%tm_name%/entry
13Entry deleteDeletes entry\translationPOST/%service%/%tm_name%/entrydelete/t5memory/%tm_name%/entrydelete
14Save all TMsFlushes all filebuffers(TMD, TMI files) into the filesystemGET/%service%_service/savetms/t5memory_service/saveatms
15Shutdown serviceFlushes all filebuffers into the filesystem and shutting down the serviceGET/%service%_service/shutdown/t5memory_service/shutdown
16Test tag replacement callFor testing tag replacementPOST/%service%_service/tagreplacement/t5memory_service/tagreplacement
17ResourcesReturns resources and service dataGET

/%service%_service/resources

/t5memory_service/resources


18Import tmx from local file(in removing lookuptable git branch)Similar to import tmx, but instead of base64 encoded file, use local path to filePOST

/%service%/%tm_name%/importlocal

/t5memory/%tm_name%/importlocal

+

19 Mass deletion of entries(from v0.6.0)It's like reorganize, but with skipping import of segments, that after checking with provided filters combined with logical AND returns true. POST

/%service%/%tm_name%/entriesdelete

/t5memory/tm1/entriesdelete

+

20New concordance search(from v0.6.0)It's extended concordance search, where you can search in different field of the segmentPOST

/%service%/%tm_name%/search

/t5memory/tm1/search


21Get segment by internal keyExtracting segment by it's location in tmd file. POST

/%service%/%tm_name%/getentry

/t5memory/tm1/getentry


22NEW Import tmxImports tmx in non-base64 formatPOST

/%service%/%tm_name%/importtmx

/t5memory/tm1/tmporttmx

+

23NEW import in internal format(tm)Extracts tm zip attached to request(it should contains tmd and tmi files) into MEM folderPOST

/%service%/%tm_name%/
("multipart/form-data")

/t5memory/tm1/

("multipart/form-data")


24NEW export tmxExports tmx file as a file. Could be used to export selected number of segments starting from selected positionGET
(could be with body)

/%service%/%tm_name%/download.tmx

/t5memory/tm1/download.tmx


25NEW export tm (internal format)Exports tm archive GET

/%service%/%tm_name%/download.tm

/t5memory/tm1/download.tm



Available end points

List of TMs

PurposeReturns JSON list of TMs
RequestGET /%service%/
Params

-

Returns list of open TMs and then list of available(excluding open) in the app.

Code Block
languagejs
titleResponse
collapsetrue
Response example:
{
    "Open": [
        {
            "name": "mem2"
        }
    ],
    "Available on disk": [
        {
            "name": "mem_internal_format"
        },
        {
            "name": "mem1"
        },
        {
            "name": "newBtree3"
        },
        {
            "name": "newBtree3_cloned"
        }
    ]
}open - TM is in RAM, Available on disk - TM is not yet loaded from disk


...

Import provided base64 encoded TMX file into TM

PurposeImport provided base64 encoded TMX file into TM. Starts another thead for import. For checking import status use status call
RequestPOST /%service%/%tm_name%/import
Params

{"tmxData": "base64EncodedTmxFile" }

  • additional:
    "framingTags":
       "saveAll" - default behaviour, do nothing
       "skipAll" - skip all enclosing tags, including standalone tags
       "skipPaired" - skip only paired enclosing tags 

TM must exist
It's async, so check status using status endpoint, like with reorganize in 0.5.x and up

Handling if framing tag situation differs from source to target - for skipAll or skipPaired

If framing tags situation is the same in source and target, both sides should be treated as described above.

If framing tags only exist in source, then still they should be treated as described above.

If they only exist in target, then  nothing should be removed.

Code Block
languagejs
titleResponse
collapsetrue
Request example:{
   ["framingTags": "skipAll"["skipPaired", "saveAll"],]
   "tmxData":   "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHRteCB2ZXJzaW9uPSIxLjQiPgogIDxoZWFkZXIgY3JlYXRpb250b29sPSJTREwgTGFuZ3VhZ2UgUGxhdGZvcm0iIGNyZWF0aW9udG9vbHZlcnNpb249IjguMCIgby10bWY9IlNETCBUTTggRm9ybWF0IiBkYXRhdHlwZT0ieG1sIiBzZWd0eXBlPSJzZW50ZW5jZSIgYWRtaW5sYW5nPSJlbi1HQiIgc3JjbGFuZz0iYmctQkciIGNyZWF0aW9uZGF0ZT0iMjAxNTA4MjFUMDkyNjE0WiIgY3JlYXRpb25pZD0idGVzdCIvPgogIDxib2R5PgoJPHR1IGNyZWF0aW9uZGF0ZT0iMjAxODAyMTZUMTU1MTA1WiIgY3JlYXRpb25pZD0iREVTS1RPUC1SNTlCT0tCXFBDMiIgY2hhbmdlZGF0ZT0iMjAxODAyMTZUMTU1MTA4WiIgY2hhbmdlaWQ9IkRFU0tUT1AtUjU5Qk9LQlxQQzIiIGxhc3R1c2FnZWRhdGU9IjIwMTgwMjE2VDE2MTMwNVoiIHVzYWdlY291bnQ9IjEiPgogICAgICA8dHV2IHhtbDpsYW5nPSJiZy1CRyI+CiAgICAgICAgPHNlZz5UaGUgPHBoIC8+IGVuZDwvc2VnPgogICAgICA8L3R1dj4KICAgICAgPHR1diB4bWw6bGFuZz0iZW4tR0IiPgogICAgICAgIDxzZWc+RXRoIDxwaCAvPiBkbmU8L3NlZz4KICAgICAgPC90dXY+CiAgICA8L3R1PgogIDwvYm9keT4KPC90bXg+Cg=="
}Response example:Error in case of errorFrom v0_2_15
{ "%tm_name%":""} in case of success
Check status of import using status call
TMX import could be interrupted in case of invalid XML or TM reaching it's limit. For both cases check status request to have info about position in tmx file where it was interrupted. 
Reorganize TM



   

...

Table of Contents

Overview and API introduction

In this document the translate5 TM service REST interface is described.

The translate5 TM service is build by using the OpenTM2 Translation Memory Engine.

It provides the following functionality:

  • import new openTM2-TMs
  • delete openTM2-TMs
  • create new empty openTM2-TM
  • import TMX
  • open TM and close TM: not possible see extra section in this document. Maybe we need trigger to flush tm to the disk, but also it could be done in some specific cases...
  • query TM for Matches: one query per TM, not quering multiple TMs at once.
  • query TM for concordance search
  • extract segment by it's location
  • save new entry to TM
  • delete entry from TM
  • localy clone TM
  • reorganize TM
  • get some statistics about service
  • also you can use tagreplacement endpoint to test tag replacement mechanism

This can be achieved by the following specification of a RESTful HTTP Serive, the specification is given in the following form:

  1. URL of the HTTP Resource, where servername and an optional path prefix is configurable.
  2. HTTP Method with affected functionality
  3. Brief Description
  4. Sent and returned Body.

Request Data Format:

The transferred data in the requests is JSON and is directly done in the request body. It's should be pretty json and ends with '\n}" symbol, because of bug in proxygen that caused garbage after valid data. 

URL Format:

In this document, the OpenTM2 is always assumed under http://opentm2/.

To rely on full networking features (proxying etc.) the URL is configurable in Translate5 so that the OpenTM2 instance can also reside under http://xyz/foo/bar/.

Errors

For each request, the possible errors are listed below for each resource. In case of an error, the body should contain at least the following JSON, if it is senseful the attributes of the original representation can be added.

{

errors: [{errorMsg: 'Given tmxData is no TMX.'}]

}


Values

%service%Name of service(default - t5memory, could be changed in t5m3mory.conf file
%tm_name%

Name of Translation Memory

Examplehttp://localhost:4040/t5memory/examle_tm/fuzzysearch/?


Endpoints overview

default endpoint/example

Is async?

1Get the list of TMsReturns JSON list of TMsGET/%service%//t5memory/
2Create TM

Creates TM with the provided name

POST/%service%//t5memory/
3Create/Import TM in internal formatImport and unpack base64 encoded archive of .TMD, .TMI, .MEM files. Rename it to provided namePOST/%service%//t5memory/
4Clone TM LocalyMakes clone of existing tmPOST/%service%/%tm_name%/clone/t5memory/my+TM/clone
(+is placeholder for whitespace in tm name, so there should be 'my TM.TMD' and 'my TM.TMI'(and in pre 0.5.x 'my TM.MEM' also) files on the disk )
tm name IS case sensetive in url

5Reorganize TMReorganizing tm(replacing tm with new one and reimporting segments from tmd) - asyncGET/%service%/%tm_name%/reorganize/t5memory/my+other_tm/reorganize+ in 0.5.x and up
5Delete TMDeletes .TMD, .TMI files DELETE/%service%/%tm_name%//t5memory/%tm_name%/
6Import TMX into TMImport provided base64 encoded TMX file into TM - asyncPOST/%service%/%tm_name%/import/t5memory/%tm_name%/import+
7Export TMX from TMCreates TMX from tm. Encoded in base64GET/%service%/%tm_name%//t5memory/%tm_name%/
8Export in Internal formatCreates and exports archive with .TMD, .TMI files of TMGET/%service%/%tm_name%//t5memory/%tm_name%/status
9

Status of TM 

Returns status\import status of TMGET/%service%/%tm_name%/status/t5memory/%tm_name%/status
10Fuzzy searchReturns entries\translations with small differences from requestedPOST/%service%/%tm_name%/fuzzysearch/t5memory/%tm_name%/fuzzysearch
11Concordance searchReturns entries\translations that contain requested segmentPOST/%service%/%tm_name%/concordancesearch/t5memory/%tm_name%/concordancesearch
12Entry updateUpdates entry\translation POST/%service%/%tm_name%/entry/t5memory/%tm_name%/entry
13Entry deleteDeletes entry\translationPOST/%service%/%tm_name%/entrydelete/t5memory/%tm_name%/entrydelete
14Save all TMsFlushes all filebuffers(TMD, TMI files) into the filesystemGET/%service%_service/savetms/t5memory_service/saveatms
15Shutdown serviceFlushes all filebuffers into the filesystem and shutting down the serviceGET/%service%_service/shutdown/t5memory_service/shutdown
16Test tag replacement callFor testing tag replacementPOST/%service%_service/tagreplacement/t5memory_service/tagreplacement
17ResourcesReturns resources and service dataGET

/%service%_service/resources

/t5memory_service/resources


18Import tmx from local file(in removing lookuptable git branch)Similar to import tmx, but instead of base64 encoded file, use local path to filePOST

/%service%/%tm_name%/importlocal

/t5memory/%tm_name%/importlocal

+

19 Mass deletion of entries(from v0.6.0)It's like reorganize, but with skipping import of segments, that after checking with provided filters combined with logical AND returns true. POST

/%service%/%tm_name%/entriesdelete

/t5memory/tm1/entriesdelete

+

20New concordance search(from v0.6.0)It's extended concordance search, where you can search in different field of the segmentPOST

/%service%/%tm_name%/search

/t5memory/tm1/search


21Get segment by internal keyExtracting segment by it's location in tmd file. POST

/%service%/%tm_name%/getentry

/t5memory/tm1/getentry


22NEW Import tmxImports tmx in non-base64 formatPOST

/%service%/%tm_name%/importtmx

/t5memory/tm1/tmporttmx

+

23NEW import in internal format(tm)Extracts tm zip attached to request(it should contains tmd and tmi files) into MEM folderPOST

/%service%/%tm_name%/
("multipart/form-data")

/t5memory/tm1/

("multipart/form-data")


24NEW export tmxExports tmx file as a file. Could be used to export selected number of segments starting from selected positionGET
(could be with body)

/%service%/%tm_name%/download.tmx

/t5memory/tm1/download.tmx


25NEW export tm (internal format)Exports tm archive GET

/%service%/%tm_name%/download.tm

/t5memory/tm1/download.tm



Available end points

List of TMs

PurposeReturns JSON list of TMs
RequestGET /%service%/
Params

-

Returns list of open TMs and then list of available(excluding open) in the app.

Code Block
languagejs
titleResponse
collapsetrue
Response example:
{
    "Open": [
        {
            "name": "mem2"
        }
    ],
    "Available on disk": [
        {
            "name": "mem_internal_format"
        },
        {
            "name": "mem1"
        },
        {
            "name": "newBtree3"
        },
        {
            "name": "newBtree3_cloned"
        }
    ]
}open - TM is in RAM, Available on disk - TM is not yet loaded from disk




Create TM

PurposeCreates TM with the provided name(tmd and tmi files in/MEM/ folder)
RequestPost /%service%/%tm_name%/
Params

Required: name, sourceLang


Code Block
languagejs
titleResponse
collapsetrue
Request example 
{    "name": "examle_tm",  // this name would be used as filename for .TMD and .TMI files   
   {  "sourceLang": "bg-BG"}  // should match lang in languages.xml
   {"data": "base64_encoded_archive_see_import_in_internal_format"}
   ["loggingThreshold": 0]
}
this endpoint could work in 2 ways, like creation of new tm (then sourceLang is required and data can be skipped) or importing archived .tm(then sourceLang can be skipped, but data is required)it's possible to add memDescription in this stage, but this should be explored more if needed

Response example:Success:{
"name": "examle_tm",
}
TM already exists: 
{
    "ReturnValue": 7272,
    "ErrorMsg": "::ERROR_MEM_NAME_EXISTS:: TM with this name already exists: examle_tm1; res = 0"
}



Create/Import TM in internal format

PurposeImport and unpack base64 encoded archive of .TMD, .TMI, .MEM(in pre 0.5.x versions) files. Rename it to provided name
RequestPOST /%service%/
Params

{    "name": "examle_tm",    "sourceLang": "bg-BG" , "data":"base64EncodedArchive" }

or alternatively data could be provided in non-base64 binary format as a file attached to the request


curl -X POST \ -H "Content-Type: application/json" \ -F "file=@/path/to/12434615271d732fvd7te3.gz;filename=myfile.tg" \ -F "json_data={\"name\": \"TM name\", \"sourceLang\": \"en-GB\"}" \ http://t5memory:4045/t5memory

Do not import tms created in other version of t5memory. Starting from 0.5.x tmd and tmi files has t5memory version where they were created in the header of the file, and different middle version(0.5.x) or global version(0.5.x) would be represented as 
version mismatch. Instead export tmx in corresponding version and create new empty tm and import tmx in new version. 

This would create example_tm.TMD(data file) and example.TMI(index file) in MEM folder
If there are "data" provided, no "sourceLang" required and vice versa - base64 data should be base64 encoded .tm file(which is just archive that contains .tmd and .tmi files 
If there are no "data" - new tm would be created, "sourceLang" should be provided and should be match with lang in languages.xml

In 0.6.20 and up data could be send as attachment instead of base64 encoded. Content-type then should be set to "multipart/form-data" and then json(with name of new tm) should be provided with json_data key(search is made this way: 

part.headers.at("Content-Disposition").find("name=\"json_data\"")

curl command example : curl -X POST \
-H "Content-Type: application/json" \
-F "file=@/path/to/12434615271d732fvd7te3.tm;filename=myfile.tm" \
-F "json_data={\"name\": \"TM name\", \"sourceLang\": \"en-GB\"}" \
http://t5memory:4045/t5memory Response example:{ "name": "examle_tm" }


Code Block
languagejs
titleResponse
collapsetrue
Request example:{ "name": "mem_internal_format", "data":"UEsDBBQACAgIAPmrhVQAAAAAAAAAAAAAAAAWAAQAT1RNXy1JRDE3NS0wXzJfNV9iLk1FTQEAAADtzqEKgDAQgOFTEHwNWZ5swrAO0SBys6wfWxFBDILv6uOI2WZQw33lr38GbvRIsm91baSiigzFEjuEb6XHEK\/myX0PXtXsyxS2OazwhLDWeVTaWgEFMMYYY\/9wAlBLBwhEWTaSXAAAAAAAAAAACAAAAAAAAFBLAwQUAAgICAD5q4VUAAAAAAAAAAAAAAAAFgAEAE9UTV8tSUQxNzUtMF8yXzVfYi5UTUQBAAAA7d3Pa5JxHMDxz+Ns09phDAYdPfaDyQqWRcYjS9nGpoYZhBeZMCISW2v2g5o6VkqQONk\/0KVzh4IoKAovnboUo1PHbuuwU8dSn8c9Pk2yTbc53y+R5\/P9fL7P1wf5Ps9zep5vIOy3iMiSiPLn0yPrQ7In+rStTQARi\/bV9chEyHcxGPIKAGDnPonl21SsHNmUYNgfHZ70nnKNDo9ET0dHozFn2L+Ll9uxZPzazPz1mYQAAAAAAAAAAAAAAAAAAAAAAAAAANDtBkXRoj5Zk7OqSFZ9q35Vn6khNa6W2wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdBKbKHK4Em1omT5DxV6J7FrmkKFypBKt9FczvYaKtr+2DLpiqPTWVayGiq2uYjFUpC7VI6aElN8F8JPn\/QEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2ANW7U0Ag9Iv60MnT4j8uLBZ\/X5+7dxn1ztX6Uy5AgAAAAAAAAAAAAAAAAAAgA6nL1qFjmc1rAO2IwNN9bL9u4ulVUeEfcQqQAfxSNtltshZaytB7jalZZ2a5KhFGT3Qr\/ztv1pkzAnP1v06+F7UxL22tRzSNf6aFq08MdoiY078\/znmkTZo5Qm2YdoOSLSyDdbaVUop\/Cj3cDm14I6\/uqf++nDUN1u4lS+k9MbKXL4QK72+775U+phOpp8sucdK728X5nK5hVT+weJqbTiHjMiNzWG1yNxWvI8rvxZ9cTfycj71NH1nsZgbf54uJlKryWy6GFlueBT6xHrzJRupDqkPXc9eyyduJmbLkf6\/mlYRDgQDPtO++3\/uYvsazANfYHx68vLEsSvOKedxqa\/hAGowD4Jh\/1X\/dH1X5sEBZpoH6E6\/AVBLBwj3gRyzjAIAAAAAAAAAAAEAAAAAAFBLAwQUAAgICAD5q4VUAAAAAAAAAAAAAAAAFgAEAE9UTV8tSUQxNzUtMF8yXzVfYi5UTUkBAAAA7d3PS9NhHMDxz\/Y1nbp0zfw2Vw6CEjooJkkFPs9DZZaFCiIRHRxKoJUIFXk06iB0kS5Fvw6dhDp28FDgOSqiIKQ\/ICQMhIIuYVnJt2f7eK2M2Ps1xp49b8Y+fP6ArXegJy4iV0RiPx6BNAXyT6ysrKhXlLZ49PwlkKP9hw\/19XcKAOD3PZX42+PDP0+JWN9AT765u3P33vbm1nxbvj0\/3DLQ0y3r5uClsZGhC2eGxgUAAAAAAAAAAAAAAAAAAAAAAAAAgFKXllh0ahQbLHeInDb3Xc6NWrF77Jibcr22zC2YY6bVLNoX5qp97Pa5SbPc8ci8sqHpd1k7a2+ZN+6eFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4YxISk8bVUyq6eVa905dtqtxO3fBlqyqnkrW+ZFVZCGp8aVDl9ZeELxlVjhRNsEWVa+UffAlVuf78rC\/1eoK20JfNqnzt3OhLnSp1DZW+bFJl\/467vqRUuVxV5UutKts\/JX2pUWUyXvie9OopE5U7QWEHSfWZXdmPvlSr8i75xJcqVT7fPOdLpSqj5+t9Sahy8UBhOxWqLEph6nJVHhZNvUFPXbS3MlXyYWFvgSon3xf2FldlpGiCmCoPiiYQVbLR3or\/ZT0tS04AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMC6K4t+ZSAtOWkKQpOSeTfnZty0m3CDrsu1uNB9swv2pZ21IlN23J6w1uZsuV0y82bOzJhpM2EGTZdpMaERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPjrUmteK0RypXifid5n1tyX6j7+9\/vvUEsHCGo104BhAgAAAAAAAAAAAQAAAAAAUEsBAgAAFAAICAgA912FVERZNpJcAAAAAAgAABYABAAAAAAAAAAAALSBAAAAAE9UTV8tSUQxNzUtMF8yXzVfYi5NRU0BAAAAUEsBAgAAFAAICAgA\/F2FVPeBHLOMAgAAAAABABYABAAAAAAAAAAAALSBrAAAAE9UTV8tSUQxNzUtMF8yXzVfYi5UTUQBAAAAUEsBAgAAFAAICAgA\/F2FVGo104BhAgAAAAABABYABAAAAAAAAAAAALSBiAMAAE9UTV8tSUQxNzUtMF8yXzVfYi5UTUkBAAAAUEsGBiwAAAAAAAAAHgMtAAAAAAAAAAAAAwAAAAAAAAADAAAAAAAAANgAAAAAAAAAOQYAAAAAAABQSwYHAAAAABEHAAAAAAAAAQAAAFBLBQYAAAAAAwADANgAAAA5BgAAAAA=" }
//you can skip data if you send it as attachment, but then set content-type to  multipart/form-data and send json with json_body key
// 

TM already exists:
{
  "ReturnValue": 65535,
  "ErrorMsg": ""
}




Clone TM localy

PurposeCreates TM with the provided name
RequestPost /%service%/%tm_name%/clone
Params

Required: name, sourceLang

Endpoint is sync(blocking)

Code Block
languagejs
titleResponse
collapsetrue
Request example 
{    "newName": "examle_tm" // when cloning, cloned tm would be renamed to this name(source tm is in url)
}

Response example:
Success: 
{
    "msg": "newBtree3_cloned2 was cloned successfully",
    "time": "5 ms"
}

 Failure: 
{
    "ReturnValue": -1,
    "ErrorMsg": "'dstTmdPath' = /home/or/.t5memory/MEM/newBtree3_cloned.TMD already exists; for request for mem newBtree3; with body = {\n    \"newName\": \"newBtree3_cloned\"\n}"
}



Delete TM

PurposeDeletes .TMD, .TMI, .MEM files 
RequestDelete /%service%/%tm_name%/
Params

-


Code Block
languagejs
titleResponse
collapsetrue
Response example:
success:
{
    "newBtree3_cloned2": "deleted"
},


Code Block
languagejs
titleResponse
collapsetrue
Response example:
failed:
{
    "newBtree3_cloned2": "not found"
}



Import binary TMX file into TM

PurposeImport provided base64 encoded TMX file into TM. Starts another thead for import. For checking import status use status call
RequestPOST /%service%/%tm_name%/importtmx
Params

Request has a file attached and a body as an option,

Implemented in 0.6.19
here are curl command to test:

curl -X POST \ -H "Content-Type: application/json" \ -F "file=@/path/to/12434615271d732fvd7te3.tmx;filename=myfile.tmx" \ -F "json_data={\"framingTags\": \"value\", \"timeout\": 1500}" \ http://t5memory:4045/t5memory/{memory_name}/importtmx

Body should be provided in multiform under json_data key
Body(optional): 

{

 ["framingTags": "saveAll"],  // framing tags behaviour 

 [timeout: 100] // timeout in sec after which import stops, even if it doesn't reach end of tmx yet

}

  • additional:
    "framingTags":
       "saveAll" - default behaviour, do nothing
       "skipAll" - skip all enclosing tags, including standalone tags
       "skipPaired" - skip only paired enclosing tags 

TM must exist
It's async, so check status using status endpoint

TMX import could be interrupted in case of invalid XML or TM reaching it's limit or timeout. For both cases check status request to have info about position in tmx file where it was interrupted. 

Handling if framing tag situation differs from source to target - for skipAll or skipPaired

If framing tags situation is the same in source and target, both sides should be treated as described above.

If framing tags only exist in source, then still they should be treated as described above.

If they only exist in target, then  nothing should be removed.





Reorganize TM

PurposeReorganizes tm and fixing issues.
RequestGET /%service%/%tm_name%/reorganize
Headers

Accept - applicaton/xml

up to v0.4.x reorganize is sync, so t5memory 
starting from 0.5.x is async, so you can check status of reorganize similar to how you can check status for importTMX

Under the hood it creates new tm with $Org- prefix, then reimport all segments one-by-one, and then deletes original TM and rename reorganized TM to replace original. 
This request should flush tm(from RAM to the disk) before reorganizing


reorganize would check this condition

if (fValidXmlInSrc && fValidXmlInTrg && (pProposal->getSourceLen

Reorganizes tm and fixing issues.
RequestGET /%service%/%tm_name%/reorganize
Headers

Accept - applicaton/xml

up to v0.4.x reorganize is sync, so t5memory 
starting from 0.5.x is async, so you can check status of reorganize similar to how you can check status for importTMX
Under the hood it creates new tm with $Org- prefix, then reimport all segments one-by-one, and then deletes original TM and rename reorganized TM to replace original. 
This request should flush tm(from RAM to the disk) before reorganizing

reorganize would check this condition

if (fValidXmlInSrc && fValidXmlInTrg && (pProposal->getSourceLen() != 0) && (pProposal->getTargetLen() != 0) &&
(szTargetLanguage[0] != EOS) && (szTagTable[0] != EOS) )

, and in case if this condition is true and then it passes segment to putProposal function, which is also used by UpdateRequest and ImportTmx request, so other 
issues could be connected to updating new tm.


In 0.4.48 reorganize responce would look like this

{
"too_long_reorg_0_4":"reorganized",
"time":"37 sec",
"reorganizedSegmentCount":"9424",
"invalidSegmentCount":"0"
}
so if there is invalid segments, inspect t5memory log

...

String with required 
EXACT or CONCORDANCE 
(or CONTAINS, what's equal to CONCORDANCE)
words and some optional, like
CASEINSENSETIVE for non case sensetive comparison,
WHITESPACETOLERANT for
modifying whitespaces(result of this actions you can see in filters in responce)
INVERTED  for applying filter in inverted state, so to return false on match and true 
if no match. Logical NOT
Attributes is not case sensetive, 
Separator doen't matters

Sets type of search for corresponding field. 
If you set, for example, "authorSearchMode" = "EXACT", but don't provide any
author in request, author field would be "", so request would look for segments, 
where author equals to "". The same is true for other fields
Examples:
1)
"source": "the  text inside"
"sourceSearchMode":"CONTAINS, CASEINSENSETIVE, WHITESPACETOLERANT, INVERTED", - search would be for all segments, which doesn't contains "the text inside" in non case sensetive mode and with normalizing whitespaces.
2) 
"author": "Ed Sheeran",
"authorSearchMode" = "Exact", -search would be done on exact case sensetive matches with "Ed Sheeran" in author field
3) 
"author": "Ed Sheeran",
"authorSearchMode" = "CASEINSENSETIVE", - ERROR, search mode(Exact\Contains) is not selected

4) "author": "Ed Sheeran",  - ERROR, search mode(Exact\Contains) is not selected

5) "authorSearchMode" = "CONTAINS",- OK, filter would check if segment contains "", so every segment would return true then

New Concordance search

PurposeReturns entries\translations that fits selected filters. 
RequestPOST /%service%/%tm_name%/search
Params

Required: NONE

iNumOfProposal -  limit of found proposals - max is 200, if 0 → use default value '5' 

Search is made segment-by segment, and it's checking segment if it fits selected filters. You can search for EXACT or CONCORDANCE matches in this fields:
source, target, document, author, addInfo, context
To set filter, use it's SearchMode field, otherwise filter would be disabled. So you have sourceSearchMode, targetSearchMode, documentSearchMode,
authorSearchMode, addInfoSearchMode, contextSearchMode 

Search mode should be set explicitly to CONTAINS/CONCORDANCE or EXACT, otherwise filter would be ignored. But also each searchMode could have additional search parameters "CONTAINS, caseinsensetive, WHITESPACETOLERANT, INVERTED", all that values is not important, as well as delimiter. By default search is case sensetive. If you add Inverted option, check for that filter would be reverted. 
To check how filters would be parsed, check json in responce.  Field with that info could look like this:

"Filters":"
Search filter, field: SOURCE FilterType::CONTAINS SearchStr: 'THE'; Options: SEARCH_FILTERS_NOT|SEARCH_CASEINSENSITIVE_OPT|SEARCH_WHITESPACETOLERANT_OPT|;\n
Search filter, field: TARGET FilterType::EXACT SearchStr: ''; Options: SEARCH_CASEINSENSITIVE_OPT|;\n
Search filter, field: ADDINFO FilterType::CONTAINS SearchStr: 'some add info'; Options: SEARCH_WHITESPACETOLERANT_OPT|;\n
Search filter, field: CONTEXT FilterType::EXACT SearchStr: 'context context'; Options: ;\nSearch filter, field: AUTHOR FilterType::CONTAINS SearchStr: ''; Options: ;\n
Search filter, field: DOCUMENT FilterType::CONTAINS SearchStr: 'evo3_p1137_reports_translation_properties_de_fr_20220720_094902'; Options: SEARCH_FILTERS_NOT|;\n
Search filter, field: TIMESTAMP FilterType::RANGE Range: 20000121T115234Z - 20240121T115234Z Options: ;\n"
,

It's possible to apply filter just with SearchMode, like if you would type "authorSearchMode": "exact",but there would be no "author" field, it would look for segments, where author field is empty.

Also there are  timespan parameter, to set it, use this fields and format:

"timestampSpanStart":"20000121T115234Z",
"timestampSpanEnd":"20240121T115234Z",

You should set both parameters to apply filter, otherwise you would get error as return.  Check output to see how it was parsed and applied.
By default all mentioned filters is applied in logical and combination, but you can change that globaly with adding 

"logicalOr": 1
Then all mentioned filters would be applied in logical or combination(please, use 1 to set this to true, boolean type is not supported by json parser in t5memory). Supported since 0.6.5

"onlyCountSegments":1

Instead of returning segments, just count them and return counter in 

"NumOfFoundSegments":22741

Also there are lang filters, they would always be applied to selection of segments that passed previous filters, so value of  "logicalOr": 1,  wouldn't be applied to that.
To set language filters, use this fields:

"sourceLang":"en-GB",
"targetLang":"de",

Lang filters could be applied with major lang feature, so source lang in this case would be applied as exact filter for source lang, but target lang would check if langs is in the same lang group. That check is done in languages.xml file with isPreferred flag.
Lang filters and if filters is combined in logical or or logical and you can check in  GlobalSearchOptions  field of responce. It could look like this: 

"GlobalSearchOptions":"SEARCH_FILTERS_LOGICAL_OR|SEARCH_EXACT_MATCH_OF_SRC_LANG_OPT, lang = en-GB|SEARCH_GROUP_MATCH_OF_TRG_LANG_OPT, lang = de",

Other that you can send is:

"searchPosition":"8:1",
"numResults":2,
"msSearchAfterNumResults":250
"loggingThreshold": 4 - check other requests,

So search position is position where to start search internaly in btree. This search is limited by num of found segment(set by numResults) or timeout(set by msSearchAfterNumResults), but timeout would be ignored in case if there are no segments in the tm to fit params.  Max  numResults is 200.

You can send empty json and search would work fine, but it would just return first 5 segments in tm
You can go through all segment  with using this 2 fields
"searchPosition":"8:1",
"numResults":200 

and just updating  searchPosition with  NewSearchPosition
from responce.


Code Block
languagejs
titleResponse
collapsetrue
{     
    "logicalOr": 1,
     "source":"the",
    "sourceSearchMode":"CONTAINS, CASEINSENSETIVE, WHITESPACETOLERANT, INVERTED",
    
    "target":"",
    "targetSearchMode":"EXACT, CASEINSENSETIVE",
    
    "document":"evo3_p1137_reports_translation_properties_de_fr_20220720_094902",
    "documentSearchMode":"CONTAINS, INVERTED",
    
     "author":"some author",
     "authorSearchMode":"CONTAINS",

    "timestampSpanStart": "20000121T115234Z",
    "timestampSpanEnd": "20240121T115234Z",

    "addInfo":"some add info",
    "addInfoSearchMode":"CONCORDANCE, WHITESPACETOLERANT",


    "context":"context context",
    "contextSearchMode":"EXACT",
    
    "sourceLang":"en-GB", 
    "targetLang":"SV",  
    "searchPosition": "8:1",
    "numResults": 2,
    "msSearchAfterNumResults": 25,
    "loggingThreshold": 3
}



So here search would be done in logical or way, so if any of source, target, document, context, author, timestamp filters returns true, result would be added to set, which then would be filtered out by sourceLang on exact match check and targetLang on groupLang check.
Search would start from position "8:1"(tm data start at "7:1" but if you wan't to start from the beggining, just avoid that param. 
numResuts:2 - so if there would be 2 segments found, search would end
"msSearchAfterNumResults": 25 - 25ms after first found segment, search would end, even if more segments was found, responce would contain "NewSearchPosition": "10:1", which can be used in searchPosition to continue search

Response example:Success:
example{
"Filters": "Search filter, field: SOURCE FilterType::CONTAINS SearchStr: 'THE'; Options: SEARCH_FILTERS_NOT|SEARCH_CASEINSENSITIVE_OPT|SEARCH_WHITESPACETOLERANT_OPT|;\n
Search filter, field: TARGET FilterType::EXACT SearchStr: ''; Options: SEARCH_CASEINSENSITIVE_OPT|;\n
Search filter, field: ADDINFO FilterType::CONTAINS SearchStr: 'some add info'; Options: SEARCH_WHITESPACETOLERANT_OPT|;\n
Search filter, field: CONTEXT FilterType::EXACT SearchStr: 'context context'; Options: ;\n
Search filter, field: AUTHOR FilterType::CONTAINS SearchStr: ''; Options: ;\n
Search filter, field: DOCUMENT FilterType::CONTAINS SearchStr: 'evo3_p1137_reports_translation_properties_de_fr_20220720_094902'; Options: SEARCH_FILTERS_NOT|;\n
Search filter, field: TIMESTAMP FilterType::RANGE Range: 20000121T115234Z - 20240121T115234Z Options: ;\n",
"GlobalSearchOptions": "SEARCH_FILTERS_LOGICAL_OR|SEARCH_EXACT_MATCH_OF_SRC_LANG_OPT, lang = en-GB|SEARCH_GROUP_MATCH_OF_TRG_LANG_OPT, lang = sv",
"ReturnValue": 0,
"ReturnMessage": "FOUND",
"NewSearchPosition": "10:1",
"results": [
{
"source": "Congratulations on the purchase of a <ph x=\"101\"/> machine control system.",
"target": "Gratulerar till köpet av maskinstyrningsystemet <ph x=\"101\"/>.",
"segmentNumber": 5740419,
"id": "",
"documentName": "none",
"sourceLang": "en-GB",
"targetLang": "SV-SE",
"type": "Manual",
"author": "",
"timestamp": "20170327T091814Z",
"markupTable": "OTMXUXLF",
"context": "",
"additionalInfo": "",
"internalKey": "8:1"
},
{
"source": "The <ph x=\"101\"/> System is an ideal tool for increasing productivity in all aspects of the construction earthmoving industry.",
"target": "Systemet <ph x=\"101\"/> är ett verktyg som lämpar sig perfekt för att öka produktiviteten inom alla delar av bygg- och anläggningsområdet.",
"segmentNumber": 5740420,
"id": "",
"documentName": "none",
"sourceLang": "en-GB",
"targetLang": "SV-SE",
"type": "Manual",
"author": "",
"timestamp": "20170327T091814Z",
"markupTable": "OTMXUXLF",
"context": "",
"additionalInfo": "",
"internalKey": "9:1"
}
]
}
SearchPosition / NewSearchPositionFormat: "7:1"
First is segment\record number, second is target number
The NextSearchposition is an internal key of the memory for the next position on sequential access. Since it is an internal key, maintained and understood by the underlying memory plug-in (for EqfMemoryPlugin is it the record number and the position in one record),
no assumptions should be made regarding the content. It is just a string that, should be sent back to OpenTM2 on the next request, so that the search starts from there.
So is the implementation in Translate5: The first request to OpenTM2 contains SearchPosition with an empty string, OpenTM2 returns than a string in NewSearchPosition, which is just resent to OpenTM2 in the next request.

Not found:{
"ReturnValue": 0,
"NewSearchPosition": null,
"ErrorMsg": ""
}TM not found:{
"ReturnValue": 133,
"ErrorMsg": "OtmMemoryServiceWorker::concordanceSearch::"
}

Here is search request with all possible parameters:
{
"logicalOr": 1, 

  "source":"the",

   "sourceSearchMode":"CONTAINS, CASEINSENSETIVE, WHITESPACETOLERANT, INVERTED",

   "target":"", "targetSearchMode":"EXACT, CASEINSENSETIVE",

   "document":"evo3_p1137_reports_translation_properties_de_fr_20220720_094902",

    "documentSearchMode":"CONTAINS, INVERTED", 

    "author":"some author",
    "authorSearchMode":"CONTAINS",

    "timestampSpanStart": "20000121T115234Z",

    "timestampSpanEnd": "20240121T115234Z",

    "addInfo":"some add info",

    "addInfoSearchMode":"CONCORDANCE, WHITESPACETOLERANT",

    "context":"context context",

    "contextSearchMode":"EXACT",

    "sourceLang":"en-GB",

    "targetLang":"SV",

    "searchPosition": "8:1",

    "numResults": 2,

     "msSearchAfterNumResults": 25,
     "loggingThreshold": 3
}
All fields is optional, but some depends on other, so error should be returned in case of not providing required field

So request with this body would also work:
{
}

ParametervalueTypedefault valuepossible valuesrequireFielddescription
sourceLangstring""langs that can 
be matched to
langs in languages.xml
-

Filter segments on src/trg lang attribute, 

If specified lang is preffered, matching is done based on lang family,
otherwise on exact match

targetLang
searchPositionstring"" (search would
start from "7:1" 
then
"8:1" etcpoint where to start search in tmd file
numResultsint5(0....200]points how many matches return in current request
msSearchAfterNumResults0no checksets how many ms should pass between first found segment and search stop, if it didn't reach the end yet. 
loggingThreshold-1[0...6]additional field to set log level on the run
logicalOrint00 for false, any other number as true, 
example:
"logicalOr": 1, 
"onlyCountSegments": 1
by default source, target, document, author, context, addinfo, timestamp is combined in logical AND, but by sending here "OR" you can switch that to logical OR, any other value would left it in default AND state.
Doesn't apply to sourceLang and targetLang filters, they are always in AND state
onlyCountSegmentsinstead of returning segment, would go in search till the end of tm and return total number of segments, that returns true with selected filters
sourcestring""any string, example 
"source": "data in the segment"
sourceSearchModeSets what to look for in source of the segments, based on type of search, specified in sourceSearchMode(exact, concordance). If sourceSearchMode is not specified, returns an error.
targettargetSearchMode--//–(the same as above but for corresponding fields)
documentdocumentSearchMode
authorauthorSearchMode
contextcontextSearchMode
addInfoaddInfoSearchMode
timestampSpanStartstringstring with date in format
 "20240121T115234Z"
timestampSpanEndSets filter for time.  You need to provid both timestamps, or none, otherwise request would return an error. Could be used in "OR" combination in 
"logicalOr": 1,, but, maybe, it's better to change that behaviour to similar like with langs(Always AND)
timestampSpanEndtimestampSpanStart
sourceSearchModestring""-
targetSearchMode
documentSearchMode
authorSearchMode
contextSearchMode
addInfoSearchMode
, OpenTM2 returns than a string in NewSearchPosition, which is just resent to OpenTM2 in the next request.

Not found:{
"ReturnValue": 0,
"NewSearchPosition": null,
"ErrorMsg": ""
}TM not found:{
"ReturnValue": 133,
"ErrorMsg": "OtmMemoryServiceWorker::concordanceSearch::"
}



Here is search request with all possible parameters:
{
"logicalOr": 1, 

  "source":"the",

   "sourceSearchMode":"CONTAINS, CASEINSENSETIVE, WHITESPACETOLERANT, INVERTED",

   "target":"", "targetSearchMode":"EXACT, CASEINSENSETIVE",

   "document":"evo3_p1137_reports_translation_properties_de_fr_20220720_094902",

    "documentSearchMode":"CONTAINS, INVERTED", 

    "author":"some author",
    "authorSearchMode":"CONTAINS",

    "timestampSpanStart": "20000121T115234Z",

    "timestampSpanEnd": "20240121T115234Z",

    "addInfo":"some add info",

    "addInfoSearchMode":"CONCORDANCE, WHITESPACETOLERANT",

    "context":"context context",

    "contextSearchMode":"EXACT",

    "sourceLang":"en-GB",

    "targetLang":"SV",

    "searchPosition": "8:1",

    "numResults": 2,

     "msSearchAfterNumResults": 25,
     "loggingThreshold": 3
}
All fields is optional, but some depends on other, so error should be returned in case of not providing required field

So request with this body would also work:
{
}

ParametervalueTypedefault valuepossible valuesrequireFielddescription
sourceLangstring""langs that can 
be matched to
langs in languages.xml
-

Filter segments on src/trg lang attribute, 

If specified lang is preffered, matching is done based on lang family,
otherwise on exact match

targetLang
searchPositionstring"" (search would
start from "7:1" 
then
"8:1" etcpoint where to start search in tmd file
numResultsint5(0....200]points how many matches return in current request
msSearchAfterNumResults0no checksets how many ms should pass between first found segment and search stop, if it didn't reach the end yet. 
loggingThreshold-1[0...6]additional field to set log level on the run
logicalOrint00 for false, any other number as true, 
example:
"logicalOr": 1, 
"onlyCountSegments": 1
by default source, target, document, author, context, addinfo, timestamp is combined in logical AND, but by sending here "OR" you can switch that to logical OR, any other value would left it in default AND state.
Doesn't apply to sourceLang and targetLang filters, they are always in AND state
onlyCountSegmentsinstead of returning segment, would go in search till the end of tm and return total number of segments, that returns true with selected filters
sourcestring""any string, example 
"source": "data in the segment"
sourceSearchModeSets what to look for in source of the segments, based on type of search, specified in sourceSearchMode(exact, concordance). If sourceSearchMode is not specified, returns an error.
targettargetSearchMode--//–(the same as above but for corresponding fields)
documentdocumentSearchMode
authorauthorSearchMode
contextcontextSearchMode
addInfoaddInfoSearchMode
timestampSpanStartstringstring with date in format
 "20240121T115234Z"
timestampSpanEndSets filter for time.  You need to provid both timestamps, or none, otherwise request would return an error. Could be used in "OR" combination in 
"logicalOr": 1,, but, maybe, it's better to change that behaviour to similar like with langs(Always AND)
timestampSpanEndtimestampSpanStart
sourceSearchModestring""String with required 
EXACT or CONCORDANCE 
(or CONTAINS, what's equal to CONCORDANCE)
words and some optional, like
CASEINSENSETIVE for non case sensetive comparison,
WHITESPACETOLERANT for
modifying whitespaces(result of this actions you can see in filters in responce)
INVERTED  for applying filter in inverted state, so to return false on match and true 
if no match. Logical NOT

Attributes is not case sensetive, 
Separator doen't matters
-

Sets type of search for corresponding field. 
If you set, for example, "authorSearchMode" = "EXACT", but don't provide any
author in request, author field would be "", so request would look for segments, 
where author equals to "". The same is true for other fields
Examples:
1)
"source": "the  text inside"
"sourceSearchMode":"CONTAINS, CASEINSENSETIVE, WHITESPACETOLERANT, INVERTED", - search would be for all segments, which doesn't contains "the text inside" in non case sensetive mode and with normalizing whitespaces.
2) 
"author": "Ed Sheeran",
"authorSearchMode" = "Exact", -search would be done on exact case sensetive matches with "Ed Sheeran" in author field
3) 
"author": "Ed Sheeran",
"authorSearchMode" = "CASEINSENSETIVE", - ERROR, search mode(Exact\Contains) is not selected

4) "author": "Ed Sheeran",  - ERROR, search mode(Exact\Contains) is not selected


5) "authorSearchMode" = "CONTAINS",- OK, filter would check if segment contains "", so every segment would return true then

targetSearchMode
documentSearchMode
authorSearchMode
contextSearchMode
addInfoSearchMode






Concordance search

PurposeReturns entries\translations that contain requested segment
RequestPOST /%service%/%tm_name%/concordancesearch
Params

Required: searchString - what we are looking for , searchType ["Source"|"Target"|"SourceAndTarget"] - where to look

iNumOfProposal -  limit of found proposals - max is 20, if 0 → use default value '5' 


Code Block
languagejs
titleResponse
collapsetrue
Request example:
{
    "searchString": "The",
    "searchType": "source", // could be Source, Target, SourceAndTarget - says where to do search
    ["searchPosition": "",] 
    ["numResults": 20,]
    ["msSearchAfterNumResults": 250,]
	["loggingThreshold": 0]
}
Response example:Success:
example_new{
  "ReturnValue": "ENDREACHED_RC",
  "NewSearchPosition": null,
  "results": [
    {
      "source": "The end",
      "target": "The target",
      "segmentNumber": 0,
      "id": "",
      "documentName": "Te2.xlf",
      "sourceLang": "de-DE",
      "targetLang": "EN-GB",
     "type": "Manual",
     "author": "THOMAS LAURIA",
     "timestamp": "20231228T171821Z",
      "markupTable": "OTMXUXLF",
      "context": "2_3",
      "additionalInfo": "",
      "internalKey": "7:1"
    }
  ]
}

example_old
{
  "ReturnValue": 0

Concordance search

PurposeReturns entries\translations that contain requested segment
RequestPOST /%service%/%tm_name%/concordancesearch
Params

Required: searchString - what we are looking for , searchType ["Source"|"Target"|"SourceAndTarget"] - where to look

iNumOfProposal -  limit of found proposals - max is 20, if 0 → use default value '5' 

Code Block
languagejs
titleResponse
collapsetrue
Request example:
{
    "searchString": "The",
    "searchType": "source", // could be Source, Target, SourceAndTarget - says where to do search
    ["searchPosition": "",] 
    ["numResults": 20,]
    ["msSearchAfterNumResults": 250,]
	["loggingThreshold": 0]
}
Response example:Success:
example_new{
  "ReturnValue": "ENDREACHED_RC",
  "NewSearchPosition": null,
  "results": [
    {
      "source": "The endFor > 100 setups.",
      "target": "The targetFür > 100 Aufstellungen.",
      "segmentNumber": 010906825,
      "id": "",
      "documentName": "Te2.xlfnone",
     "documentShortName": "NONE",
     "sourceLang": "en-GB",← rfc5646     
     "targetLang": "de-DE",← rfc5646
      "targetLangtype": "EN-GBManual",
     "typematchType": "Manualundefined",
     "author": "THOMAS LAURIA",
     "timestamp": "20231228T171821Z20190401T084052Z",
     "matchRate": 0,
     "markupTable": "OTMXUXLFOTMXML",
      "context": "2_3",
      "additionalInfo": "",
   }
  ],
  "internalKeyErrorMsg": "7:1"
    }
  ]
}

example_old"
}

Success, but with NewSearchPosition - not all TM was checked, use this position to repeat search:
{
  "ReturnValue": 0,
  "NewSearchPosition": null"8:1",
  "results": [
  {
     "source": "For > 100 setups.",
     "target": "Für > 100 Aufstellungen.",
     "segmentNumber": 10906825,
     "id": "",
     "documentName": "none",
     "documentShortName": "NONE",
     "sourceLang": "en-GB",← rfc5646 
    
     "targetLang": "de-DE",← rfc5646
     "type": "Manual",
     "matchType": "undefined",
     "author": "",
     "timestamp": "20190401T084052Z",
     "matchRate": 0,
     "markupTable": "OTMXML",
     "context": "",
     "additionalInfo": ""
   }
  ],
 "ErrorMsg": ""
}

Success, but with NewSearchPosition - not all TM was checked, use this position to repeat search:
{
  "ReturnValue": 0,
  "NewSearchPosition": "8:1",
  "results": [
  {
     "source": "For > 100 setups.",
     "target": "Für > 100 Aufstellungen.",
     "segmentNumber": 10906825,
     "id": "",
    "documentName": "none",
    "documentShortName": "NONE",
    "sourceLang": "en-GB",
    "targetLang": "de-DE",
    "type": "Manual",
     "matchType": "undefined",
     "author": "",
     "timestamp": "20190401T084052Z",
     "matchRate": 0,
     "markupTable": "OTMXML",
     "context": "",
     "additionalInfo": ""
   }
  ],
 "ErrorMsg": ""
}
SearchPosition / NewSearchPositionFormat: "7:1"
First is segmeng\record number, second is target number
The NextSearchposition is an internal key of the memory for the next position on sequential access. Since it is an internal key, maintained and understood by the underlying memory plug-in (for EqfMemoryPlugin is it the record number and the position in one record),
no assumptions should be made regarding the content. It is just a string that, should be sent back to OpenTM2 on the next request, so that the search starts from there.
So is the implementation in Translate5: The first request to OpenTM2 contains SearchPosition with an empty string, OpenTM2 returns than a string in NewSearchPosition, which is just resent to OpenTM2 in the next request.

Not found:{
"ReturnValue": 0,
"NewSearchPosition": null,
"ErrorMsg": ""
}TM not found:{
"ReturnValue": 133,
"ErrorMsg": "OtmMemoryServiceWorker::concordanceSearch::SearchPosition / NewSearchPositionFormat: "7:1"
First is segmeng\record number, second is target number
The NextSearchposition is an internal key of the memory for the next position on sequential access. Since it is an internal key, maintained and understood by the underlying memory plug-in (for EqfMemoryPlugin is it the record number and the position in one record),
no assumptions should be made regarding the content. It is just a string that, should be sent back to OpenTM2 on the next request, so that the search starts from there.
So is the implementation in Translate5: The first request to OpenTM2 contains SearchPosition with an empty string, OpenTM2 returns than a string in NewSearchPosition, which is just resent to OpenTM2 in the next request.

Not found:{
"ReturnValue": 0,
"NewSearchPosition": null,
"ErrorMsg": ""
}TM not found:{
"ReturnValue": 133,
"ErrorMsg": "OtmMemoryServiceWorker::concordanceSearch::"
}







Get entry

PurposeReturns entry that located in [recordKey:targetKey] location or error if it's empty
RequestPOST /%service%/%tm_name%/getentry
Params

Required: recordKey- it's position in the tmd file, starting from 7(first 6 it's service records)

targetKey - position in record,  starting from 1

Implemented in 0.6.24


Code Block
languagejs
titleResponse
collapsetrue
Request example:
{
    "recordKey": "8",
    "targetKey": "2"
  ["loggingThreshold": 0]
}
Response example:
Success: {
    "source": "%Project.Progress%",
    "target": "%Project.Progress%",
    "segmentId": 7,
    "documentName": "DSGVO_v27_HIDDEN.docx.sdlxliff",
    "sourceLang": "de-DE",
    "targetLang": "EN-US",
    "type": "Manual",
    "author": "",
    "timestamp": "20220706T112459Z",
    "markupTable": "OTMXUXLF",
    "context": "",
    "additionalInfo": "",
    "internalKey": "10:1"
}
Not found:
{
    "ReturnValue": 939,
    "ErrorMsg": "Requested entry not found! Next internalKey after requested is : 11;1"
}





Update entry

PurposeUpdates entry\translation 
RequestPOST /%service%/%tm_name%/entry
Params

Only sourceLang, targetLang, source and target are required


This request would made changes only in the filebuffer(so files on disk would not be changed)
To write it to the disk just call request which would flush tm to the disk as part of execution(exportTMX, exportTM, cloneTM) or using SaveAllTms request 

Code Block
languagejs
titleResponse
collapsetrue
Request example:
{
    "source": "The end",
    "target": "The target",
    "sourceLang": "en", // langs would be checked with languages.xml
    "targetLang": "de", 
//additional field
    ["documentName": "Translate5 Demo Text-en-de.xlf"],
    ["segmentNumber": 8,]
    ["author": "Thomas Lauria"],
    ["timeStamp": "20210621T071042Z"], // if there is no timestamp, current time would be used
    ["context": "2_2"], // context and addInfo would be saved in TM in the same field
    ["addInfo": "2_2"], 
    ["type": "Manual"], // could be GlobalMemory, GlobalMemoryStar, MachineTranslation, Manual, by default Undefined         
    ["markupTable": "OTMXUXLF"], //if there is no markup, default OTMXUXLF would be used. 
								 //Markup tables should be located inside ~/.t5memory/TABLE/%markup$.TBL
    ["loggingThreshold": 0],
	["save2disk": 0]   // flag if we need to flush tm to disk after update. by default is true
}

here are data struct used for search, so you can see max numbers of symbols
typedef struct _LOOKUPINMEMORYDATA
{
  char szMemory[260];
  wchar_t szSource[2050];
  wchar_t szTarget[2050];
  char szIsoSourceLang[40];
  char szIsoTargetLang[40];
  int lSegmentNum;
  char szDocName[260];
  char szMarkup[128];
  wchar_t szContext[2050];
  wchar_t szAddInfo[2050];
  wchar_t szError[512];
  char szType[256];
  char szAuthor[80];
  char szDateTime[40];
  char szSearchMode[40]; // only for concordance search
  char szSearchPos[80]; // only for concordance search
  int iNumOfProposals;
  int iSearchTime;
  wchar_t szSearchString[2050];
} LOOKUPINMEMORYDATA, *PLOOKUPINMEMORYDATA;

Response example:success:
example_new{
  "source": "The end",
  "sourceNPRepl": "The end",
  "sourceNorm": "The end",
  "target": "The target",
  "segmentNumber": 0,
  "id": "",
  "documentName": "Te2.xlf",
  "sourceLang": "DE-DE",
  "targetLang": "EN-GB",
  "type": "Manual",
  "author": "THOMAS LAURIA",
  "timestamp": "",
  "markupTable": "OTMXUXLF",
  "context": "2_3",
  "additionalInfo": "addInfo2",
  "internalKey": "8:1"
}

example_old
{
"sourceLang": "de-DE",
"targetLang": "en-GB",
"source": "The end",
"target": "The target",
"documentName": "Translate5 Demo Text-en-de.xlf",
"segmentNumber": 222,
"markupTable": "OTMXUXLF",
"timeStamp": "20210621T071042Z",
"author": "Thomas Lauria"
}

in case if similar record exists, t5memory comparing source text, 
if it's the same, t5memory would compare docName, 
if it's the same,t5memory would compare timestamps and would leave only newer one

in case if TM is alreade reached it's limit, you would get 
{
"ReturnValue": 5034,
"ErrorMsg": ""
}or{
"ReturnValue": 5035,
"ErrorMsg": ""
}




Code Block
languagejs
titleUpdateEntry Pseudo code
collapsetrue
Update entry pseudo code:update segment/import
{
  if we have triples equal match (candidate for exact match)
  {
    UpdateTmRecord
    if(updateFailed)
      AddToTMAsNewKey
      if(added) UpdateTmIndex
  }else{
    AddToTMAsNewKey
    if(added) UpdateTmIndex
  }
}

UpdateTmRecord{
  getListOfDataKeysFromIndexRecord
  sortThemByTriplesMatchesWithProposal(first have biggest match)

  foreach key untill fStop==true{
    readTmRecord // tm record is 16kB block in file, first number in "7:1"

    //compare tm record data with data passed in the get in structure
    CompareAndModifyPutData
    if(NO_ERROR) set fStop = true;
  }
}

CompareAndModifyPutData{
  if source strings are equal
    Delete old entry - with TMLoopAndDelTargetClb
  if fNewerTargetExists -> fStop = TRUE
  Loop thru target records
    loop over all target CLBs or until fStop
      if segment+file id found (exact-exact-found!)
        update time field in control block
        set fUpdate= fStop=TRUE
        update context info
      if not fStop
        goto next CLB
    endloop
    if no matching CLB has been found (if not fStop)
      add new CLB (ids, context, timestamp etc. )
    endloop
  endloop

  if fupdated, update TM record
  if !fStop (all target record have been tried & none matches )
    add new target record to end of tm record
  else
    return source_string_error // errcode for UpdateTmRecord to go to the next TM record in prepared list
}

TMLoopAndDelTargetClb{
  loop through all target records in tm record checking
    loop over all target CLBs or until fStop
      if lang + segment+file id found (exact-exact-found!)
        if entry is older
          delete it, fDel = TRUE
        else set fNewerTargetExists=TRUE(would be used in CompareAndModifyPutData)
          goon with search in next tgt CLB (control block)
      else
        goon with search in next tgt CLB (control block)
        endloop
      endif
    if not fDel
      position at next target record
  endloop
}


...