Localizing webview display strings (#18040)

* initial loc

* Fixing more loc

* Adding error messages

* Refactor localization in ObjectExplorerFilterPage

* Adding more loc strings

* Moving execution plan loc strings to webviews

* localized remaining string

* Adding new loc strings

* centralizing loc strings
This commit is contained in:
Aasim Khan 2024-09-12 23:31:08 -07:00 коммит произвёл GitHub
Родитель ffa8ea6c4c
Коммит bcec0aaad8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
32 изменённых файлов: 1319 добавлений и 560 удалений

5
.gitignore поставляемый
Просмотреть файл

@ -25,6 +25,7 @@ package.nls.*.json
/blob-report/
/playwright/.cache/
.env
# Ignore all webviews metafiles generated by esbuild while building webviews
webviews-metafile.json
/localization/l10n/
! /localization/l10n/bundle.l10n.json
# Ignore all l10n files except the default one (bundle.l10n.json)
/localization/l10n/bundle.l10n.*.json

Просмотреть файл

@ -1,11 +1,204 @@
{
"Query {0}: Query cost (relative to the script): {1}/{0} is the query number{1} is the query cost": {
"message": "Query {0}: Query cost (relative to the script): {1}",
"The name of the table object.": "The name of the table object.",
"Table name": "Table name",
"The schema that contains the table.": "The schema that contains the table.",
"Schema": "Schema",
"Description for the table.": "Description for the table.",
"Description": "Description",
"The name of the column object.": "The name of the column object.",
"Name": "Name",
"Displays the description of the column": "Displays the description of the column",
"Displays the unified data type (including length, scale and precision) for the column": "Displays the unified data type (including length, scale and precision) for the column",
"Advanced Type": "Advanced Type",
"Displays the data type name for the column": "Displays the data type name for the column",
"Type": "Type",
"The maximum length (in characters) that can be stored in this database object.": "The maximum length (in characters) that can be stored in this database object.",
"Length": "Length",
"A predefined global default value for the column or binding.": "A predefined global default value for the column or binding.",
"Default Value": "Default Value",
"Specifies whether the column may have a NULL value.": "Specifies whether the column may have a NULL value.",
"Allow Nulls": "Allow Nulls",
"Specifies whether the column is included in the primary key for the table.": "Specifies whether the column is included in the primary key for the table.",
"Primary Key": "Primary Key",
"For numeric data, the maximum number of decimal digits that can be stored in this database object.": "For numeric data, the maximum number of decimal digits that can be stored in this database object.",
"Precision": "Precision",
"For numeric data, the maximum number of decimal digits that can be stored in this database object to the right of decimal point.": "For numeric data, the maximum number of decimal digits that can be stored in this database object to the right of decimal point.",
"Scale": "Scale",
"Columns": "Columns",
"Column": "Column",
"New Column": "New Column",
"The name of the column.": "The name of the column.",
"Name of the primary key.": "Name of the primary key.",
"The description of the primary key.": "The description of the primary key.",
"Columns in the primary key.": "Columns in the primary key.",
"Primary Key Columns": "Primary Key Columns",
"Add Column": "Add Column",
"The name of the index.": "The name of the index.",
"The description of the index.": "The description of the index.",
"The columns of the index.": "The columns of the index.",
"Indexes": "Indexes",
"Index": "Index",
"New Index": "New Index",
"Foreign Column": "Foreign Column",
"The name of the foreign key.": "The name of the foreign key.",
"The description of the foreign key.": "The description of the foreign key.",
"The table which contains the primary or unique key column.": "The table which contains the primary or unique key column.",
"Foreign Table": "Foreign Table",
"The behavior when a user tries to update a row with data that is involved in a foreign key relationship.": "The behavior when a user tries to update a row with data that is involved in a foreign key relationship.",
"On Update Action": "On Update Action",
"The behavior when a user tries to delete a row with data that is involved in a foreign key relationship.": "The behavior when a user tries to delete a row with data that is involved in a foreign key relationship.",
"On Delete Action": "On Delete Action",
"The mapping between foreign key columns and primary key columns.": "The mapping between foreign key columns and primary key columns.",
"New Column Mapping": "New Column Mapping",
"Foreign Keys": "Foreign Keys",
"Foreign Key": "Foreign Key",
"New Foreign Key": "New Foreign Key",
"The name of the check constraint.": "The name of the check constraint.",
"The description of the check constraint.": "The description of the check constraint.",
"The expression defining the check constraint.": "The expression defining the check constraint.",
"Expression": "Expression",
"Check Constraints": "Check Constraints",
"Check Constraint": "Check Constraint",
"New Check Constraint": "New Check Constraint",
"About table": "About table",
"{0} issue/{0} is the number of issues": {
"message": "{0} issue",
"comment": [
"{0} is the number of issues"
]
},
"{0} issues/{0} is the number of issues": {
"message": "{0} issues",
"comment": [
"{0} is the number of issues"
]
},
"{0} {1} issue/{0} is the tab name{1} is the number of issues": {
"message": "{0} {1} issue",
"comment": [
"{0} is the tab name",
"{1} is the number of issues"
]
},
"{0} {1} issues/{0} is the tab name{1} is the number of issues": {
"message": "{0} {1} issues",
"comment": [
"{0} is the tab name",
"{1} is the number of issues"
]
},
"Generate Script": "Generate Script",
"Script As Create": "Script As Create",
"Properties": "Properties",
"No data": "No data",
"Severity": "Severity",
"Script as CREATE": "Script as CREATE",
"1 issue": "1 issue",
"{0} issues": "{0} issues",
"Issues": "Issues",
"Go there": "Go there",
"Open in new tab": "Open in new tab",
"Move Up": "Move Up",
"Move Down": "Move Down",
"Delete": "Delete",
"Error loading designer": "Error loading designer",
"Retry": "Retry",
"Loading table designer": "Loading table designer",
"Filter Settings": "Filter Settings",
"Error": "Error",
"Clear All": "Clear All",
"Close": "Close",
"OK": "OK",
"And": "And",
"Contains": "Contains",
"Not Contains": "Not Contains",
"Starts With": "Starts With",
"Not Starts With": "Not Starts With",
"Ends With": "Ends With",
"Not Ends With": "Not Ends With",
"Equals": "Equals",
"Not Equals": "Not Equals",
"Less Than": "Less Than",
"Less Than Or Equals": "Less Than Or Equals",
"Greater Than": "Greater Than",
"Greater Than Or Equals": "Greater Than Or Equals",
"Between": "Between",
"Not Between": "Not Between",
"Path: {0}/{0} is the path of the node in the object explorer": {
"message": "Path: {0}",
"comment": [
"{0} is the path of the node in the object explorer"
]
},
"The first value must be set for the {0} operator in the {1} filter/{0} is the operator for the filter{1} is the name of the filter": {
"message": "The first value must be set for the {0} operator in the {1} filter",
"comment": [
"{0} is the operator for the filter",
"{1} is the name of the filter"
]
},
"The second value must be set for the {0} operator in the {1} filter/{0} is the operator for the filter{1} is the name of the filter": {
"message": "The second value must be set for the {0} operator in the {1} filter",
"comment": [
"{0} is the operator for the filter",
"{1} is the name of the filter"
]
},
"The first value must be less than the second value for the {0} operator in the {1} filter/{0} is the operator for the filter{1} is the name of the filter": {
"message": "The first value must be less than the second value for the {0} operator in the {1} filter",
"comment": [
"{0} is the operator for the filter",
"{1} is the name of the filter"
]
},
"Property": "Property",
"Operator": "Operator",
"Value": "Value",
"Clear": "Clear",
"Publishing Changes": "Publishing Changes",
"Changes published successfully": "Changes published successfully",
"Close Designer": "Close Designer",
"Continue Editing": "Continue Editing",
"Loading Table Designer": "Loading Table Designer",
"Error loading preview": "Error loading preview",
"Update Database": "Update Database",
"Publish": "Publish",
"Preview Database Updates": "Preview Database Updates",
"Connect": "Connect",
"Advanced Connection Settings": "Advanced Connection Settings",
"Advanced": "Advanced",
"Test Connection": "Test Connection",
"Connect to SQL Server": "Connect to SQL Server",
"Parameters": "Parameters",
"Connection String": "Connection String",
"Browse Azure": "Browse Azure",
"Recent Connections": "Recent Connections",
"Query {0}: Query cost (relative to the script): {1}%/{0} is the query number{1} is the query cost": {
"message": "Query {0}: Query cost (relative to the script): {1}%",
"comment": [
"{0} is the query number",
"{1} is the query cost"
]
},
"Actual Elapsed Time": "Actual Elapsed Time",
"Actual Elapsed CPU Time": "Actual Elapsed CPU Time",
"Cost": "Cost",
"Subtree Cost": "Subtree Cost",
"Actual Number of Rows For All Executions": "Actual Number of Rows For All Executions",
"Number of Rows Read": "Number of Rows Read",
"Off": "Off",
"Metric": "Metric",
"Find Nodes": "Find Nodes",
"Save Plan": "Save Plan",
"Open XML": "Open XML",
"Open Query": "Open Query",
"Zoom In": "Zoom In",
"Zoom Out": "Zoom Out",
"Zoom to Fit": "Zoom to Fit",
"Custom Zoom": "Custom Zoom",
"Find Node": "Find Node",
"Highlight Expensive Operation": "Highlight Expensive Operation",
"Toggle Tooltips": "Toggle Tooltips",
"Object Explorer Filter": "Object Explorer Filter",
"{0} (filtered)": "{0} (filtered)",
"View More": "View More",
@ -215,7 +408,6 @@
"Invalid IP Address": "Invalid IP Address",
"Invalid Firewall rule name": "Invalid Firewall rule name",
"No Queries Available": "No Queries Available",
"Retry": "Retry",
"Create Firewall Rule": "Create Firewall Rule",
"Connecting to server \"{0}\" on document \"{1}\"./{0} is the server name{1} is the document name": {
"message": "Connecting to server \"{0}\" on document \"{1}\".",
@ -372,7 +564,6 @@
"Use T-SQL intellisense and syntax error checking on current document": "Use T-SQL intellisense and syntax error checking on current document",
"Disable intellisense and syntax error checking on current document": "Disable intellisense and syntax error checking on current document",
"Add Connection": "Add Connection",
"Connect": "Connect",
"Azure: Sign In": "Azure: Sign In",
"Sign in to your Azure subscription": "Sign in to your Azure subscription",
"Azure: Sign In with Device Code": "Azure: Sign In with Device Code",
@ -441,32 +632,9 @@
"Tenant ID is required": "Tenant ID is required",
"Server is required": "Server is required",
"User name is required": "User name is required",
"Connection String": "Connection String",
"Connection string is required": "Connection string is required",
"Sign in": "Sign in",
"Additional parameters": "Additional parameters",
"Parameters": "Parameters",
"Loading": "Loading",
"Metric": "Metric",
"Actual Elapsed Time": "Actual Elapsed Time",
"Actual Elapsed CPU Time": "Actual Elapsed CPU Time",
"Cost": "Cost",
"Subtree Cost": "Subtree Cost",
"Actual Number of Rows For All Executions": "Actual Number of Rows For All Executions",
"Number of Rows Read": "Number of Rows Read",
"Off": "Off",
"Find Nodes": "Find Nodes",
"Equals": "Equals",
"Contains": "Contains",
"Save Plan": "Save Plan",
"Open Xml": "Open Xml",
"Open Query": "Open Query",
"Zoom In": "Zoom In",
"Zoom Out": "Zoom Out",
"Zoom to Fit": "Zoom to Fit",
"Custom Zoom": "Custom Zoom",
"Find Node": "Find Node",
"Highlight Expensive Operation": "Highlight Expensive Operation",
"Toggle Tooltips": "Toggle Tooltips",
"Execution Plan": "Execution Plan"
}

Просмотреть файл

@ -7,12 +7,21 @@
<trans-unit id="++CODE++0d7668d337e375d8ccfc1a69ca8f6e22a0b0c850a78c4770b0c4aa3b0daca630">
<source xml:lang="en">&lt;default&gt;</source>
</trans-unit>
<trans-unit id="++CODE++d6bfda034106ecd656f7c676550815337c9b045baf85aa5c3b439c3ff82df1df">
<source xml:lang="en">1 issue</source>
</trans-unit>
<trans-unit id="++CODE++08fef8ce26bbc554c749504c8d169642c3039345674331079add345b808e96a7">
<source xml:lang="en">A SQL editor must have focus before executing this command</source>
</trans-unit>
<trans-unit id="++CODE++880a0618dd92395efe1446e54fe5d50854c148586fdc14f5da8aecda61c827ae">
<source xml:lang="en">A predefined global default value for the column or binding.</source>
</trans-unit>
<trans-unit id="++CODE++0ead4aa08784fedbf2a89d6c0958d7704ede494d920130913de6de5e42fdca50">
<source xml:lang="en">A query is already running for this editor session. Please cancel this query or wait for its completion.</source>
</trans-unit>
<trans-unit id="++CODE++8a8e2d4f3b4443193caa0e9b0ce9484eeeae488501d43476f2e03968124d5e90">
<source xml:lang="en">About table</source>
</trans-unit>
<trans-unit id="++CODE++ea9df7a87af305f04a7ca43d0ce60433e16504061c265ab11d0029cdf8cae372">
<source xml:lang="en">Access token expired for connection {0} with uri {1}</source>
<note>{0} is the connection id
@ -30,6 +39,9 @@
<trans-unit id="++CODE++63d01a41e50ddec3d6edfabbbf3f1c34d09f581236beab50bf510ea11e9ef4c5">
<source xml:lang="en">Actual Number of Rows For All Executions</source>
</trans-unit>
<trans-unit id="++CODE++c26c65459a782d2065f5a9cda97c098c2e49e5734d5d16c8a8c86d4c177373cc">
<source xml:lang="en">Add Column</source>
</trans-unit>
<trans-unit id="++CODE++d72d67f0f765e5584e6db8bd1e591a84914d23ff29e9f5b20d8b39125091fca0">
<source xml:lang="en">Add Connection</source>
</trans-unit>
@ -39,6 +51,18 @@
<trans-unit id="++CODE++69bcade64ab9094e6b5fd3b235f0dcc9e723977c25283af0fa746bd154fc386e">
<source xml:lang="en">Additional parameters</source>
</trans-unit>
<trans-unit id="++CODE++9f088dbebd6c3c70a5ddbc2c943b11e4ca9acea5757b0b4f2b32479f0dbb747e">
<source xml:lang="en">Advanced</source>
</trans-unit>
<trans-unit id="++CODE++d2cab259e6e6da600d35907f2b627f8bf69c49ab40f8f129b9d9f206f149a8f9">
<source xml:lang="en">Advanced Connection Settings</source>
</trans-unit>
<trans-unit id="++CODE++232bbbc747fa6709e2940f4d0eec4b819b3b007acfdacaec8f3e2e1536799bd7">
<source xml:lang="en">Advanced Type</source>
</trans-unit>
<trans-unit id="++CODE++ab4db1a876378f718e4073baa75897c34c0e7d2608d68cda6461e01de42fa962">
<source xml:lang="en">Allow Nulls</source>
</trans-unit>
<trans-unit id="++CODE++d4fd4b3da177dfc06dbcde0a7f62d637dbf3d90298fdc9b6aeba4f9230441e1f">
<source xml:lang="en">An error occurred refreshing nodes. See the MSSQL output channel for more details.</source>
</trans-unit>
@ -46,6 +70,9 @@
<source xml:lang="en">An error occurred while removing Microsoft Entra account: {0}</source>
<note>{0} is the error message</note>
</trans-unit>
<trans-unit id="++CODE++0f67514b901da8b9c613167848294cb0010b3c0e696732aa1a0c9737e5be69b1">
<source xml:lang="en">And</source>
</trans-unit>
<trans-unit id="++CODE++3d283f80f43f1833dcab882ad9efc24a86c0b17b0febb10fc37336590a7016e1">
<source xml:lang="en">Are you sure you want to disconnect?</source>
</trans-unit>
@ -92,6 +119,12 @@
<source xml:lang="en">Batch execution time: {0}</source>
<note>{0} is the batch time</note>
</trans-unit>
<trans-unit id="++CODE++c1ea3f5e7aa473034872296473c7fcf9c79344355ba4fd003120627f6ec1a5f7">
<source xml:lang="en">Between</source>
</trans-unit>
<trans-unit id="++CODE++221cedb44469e4b0b105f777c771d70c7097c40a4e3e914cec4b6ba266db1970">
<source xml:lang="en">Browse Azure</source>
</trans-unit>
<trans-unit id="++CODE++eb6b42f54c42d2832e296319f7fdad64d46aecd1ec19b0e9c80b85b7cfc6dcae">
<source xml:lang="en">CSV</source>
</trans-unit>
@ -128,12 +161,21 @@
{1} is the server name
{2} is the document name</note>
</trans-unit>
<trans-unit id="++CODE++cf51bd8ae1e56e8e81b07f1e7f35e10d580788d9e0892a8a4896c2378227f4f0">
<source xml:lang="en">Changes published successfully</source>
</trans-unit>
<trans-unit id="++CODE++37b6d72a119e5ec53d1dc71ba94cbed9566519488230f6a4e40ae82bfc8bc79f">
<source xml:lang="en">Changing database context to &quot;{0}&quot; on server &quot;{1}&quot; on document &quot;{2}&quot;.</source>
<note>{0} is the database name
{1} is the server name
{2} is the document name</note>
</trans-unit>
<trans-unit id="++CODE++c8cabf4a998e678eb3213d46a3e9e80217b7839fb5f3537ee550a65e3b2202c9">
<source xml:lang="en">Check Constraint</source>
</trans-unit>
<trans-unit id="++CODE++4a41af1285aa71f4e677bc3fa729070b3c3c0af177cb4e9f12e34f1e21045894">
<source xml:lang="en">Check Constraints</source>
</trans-unit>
<trans-unit id="++CODE++de88f00e461bb1cd413f9c556b06e1b903006bb3c0123f2e75fdff92532034af">
<source xml:lang="en">Choose An Action</source>
</trans-unit>
@ -155,15 +197,36 @@
<trans-unit id="++CODE++3b961516b68d49db85d3ded5bc5c1129e02be1a647845d77b1eb2ab5260284cb">
<source xml:lang="en">Choose a database from the list below</source>
</trans-unit>
<trans-unit id="++CODE++83b12c2216efb4fdc924e1deb5182e905e4926ed0c1c324d467107f46d5a26a9">
<source xml:lang="en">Clear</source>
</trans-unit>
<trans-unit id="++CODE++ddceb7adfdb8816e4747bc48a2221702e830340e5596a701dc0993766eba5e60">
<source xml:lang="en">Clear All</source>
</trans-unit>
<trans-unit id="++CODE++08e2c4e53c4b3b6008b7bc4d82eb29ab933d3b6c08b34eda0637fbf148fb1529">
<source xml:lang="en">Clear Recent Connections List</source>
</trans-unit>
<trans-unit id="++CODE++6bca6724e27bd109d1b946c1684e16c2c4a5d71731a9ffe5f666bdd9d9846b1e">
<source xml:lang="en">Click to connect to a database</source>
</trans-unit>
<trans-unit id="++CODE++7d9eb7acb13e24625c404401d8e88b2350e32162455885f18276cf802f7701ed">
<source xml:lang="en">Close</source>
</trans-unit>
<trans-unit id="++CODE++a9d0b49f48a51a21c93552032bd3ac0b356430187424536e274c84b493cac48e">
<source xml:lang="en">Close Designer</source>
</trans-unit>
<trans-unit id="++CODE++548e8cc0e8c2423c61f30c6e8b75a1a40c995e3be119df6272b280ab6c15a011">
<source xml:lang="en">Close the current connection</source>
</trans-unit>
<trans-unit id="++CODE++3fdc9a587693f9e63574b30ec55c2b947a7fb4ba5fd11f0cf213072f53d91bdd">
<source xml:lang="en">Column</source>
</trans-unit>
<trans-unit id="++CODE++53aade77cd69a77bbb51bf8ca4e7ea8b282db75edce8883775e47042478d35b5">
<source xml:lang="en">Columns</source>
</trans-unit>
<trans-unit id="++CODE++9504ef48c5eab40c3e3a086cbbdc3d70b44e607552db6adfbdd7c278ddabe357">
<source xml:lang="en">Columns in the primary key.</source>
</trans-unit>
<trans-unit id="++CODE++eb83f1820ce359dc5c9aa6ca4d08fad60256a9808c58ad93f89db3c182908364">
<source xml:lang="en">Confirm to clear recent connections list</source>
</trans-unit>
@ -173,6 +236,9 @@
<trans-unit id="++CODE++1a2303ede07493acc7caaa7c737f3c52bcc9cf04372be19ed1b0af6b9f2c791e">
<source xml:lang="en">Connect</source>
</trans-unit>
<trans-unit id="++CODE++8a8bef20f041d1f1fc0ea7966a3fa58563c599617464a303258ed302ddca5a79">
<source xml:lang="en">Connect to SQL Server</source>
</trans-unit>
<trans-unit id="++CODE++b6c3dc8ba33b3a93b9060f81da8fa7d496f07487cec7a12353257242b2ea9e24">
<source xml:lang="en">Connected to server &quot;{0}&quot; on document &quot;{1}&quot;. Server information: {2}</source>
<note>{0} is the server name
@ -215,6 +281,9 @@
<trans-unit id="++CODE++2eaecb3d0cf1282f01fc09568b63dc633753a0dbf337365d929d9c28df3d6ca4">
<source xml:lang="en">Contains</source>
</trans-unit>
<trans-unit id="++CODE++56fd975f4cea21a748feabb6cb1cfb49161141245c2d4d1698cee7ae99c69bf2">
<source xml:lang="en">Continue Editing</source>
</trans-unit>
<trans-unit id="++CODE++e21f935f11d7e966dbbae78da9daa378fe8142a14e7c0cd7434183005faa6c5c">
<source xml:lang="en">Copy</source>
</trans-unit>
@ -245,12 +314,24 @@
<trans-unit id="++CODE++e97a0773fb7b656c174155270bd9ded70bc82caa0fc5d65b3ba24871577a5b08">
<source xml:lang="en">Database name</source>
</trans-unit>
<trans-unit id="++CODE++647cc4253428b25fe686fa8d5d5da5841fed53ad85395cdd43920d0226900c1d">
<source xml:lang="en">Default Value</source>
</trans-unit>
<trans-unit id="++CODE++b6ca9a06ebcc8ea511648b46b103859960924b42fa98231c0ca4b69b84943687">
<source xml:lang="en">DefinitionRequestCompleted</source>
</trans-unit>
<trans-unit id="++CODE++fe0ec38fb92c70d80fd5a36ff72c37cb3ed759bba91373c96a21bde631e03db3">
<source xml:lang="en">DefinitionRequested</source>
</trans-unit>
<trans-unit id="++CODE++e2d0a54968ead24efc0dffa6ac78fc606dceec34a0f586177a74a54cc2272cf8">
<source xml:lang="en">Delete</source>
</trans-unit>
<trans-unit id="++CODE++526e0087cc3f254d9f86f6c7d8e23d954c4dfda2b312efc29194ae8a860106ba">
<source xml:lang="en">Description</source>
</trans-unit>
<trans-unit id="++CODE++b16cf0590a6c78b2e8047509582e5448bd55e408cd112bd1f064e34529f6ce3d">
<source xml:lang="en">Description for the table.</source>
</trans-unit>
<trans-unit id="++CODE++6fbed214e0ea21c683db0ba2d648ef09b11edf4b4bb23835d4fdda84b5d097f3">
<source xml:lang="en">Disable intellisense and syntax error checking on current document</source>
</trans-unit>
@ -267,6 +348,15 @@
<trans-unit id="++CODE++48845bff334a50a59aaecf499f28a7a24c3b4b891b8b18a9f1169ad8e8a6b261">
<source xml:lang="en">Dismiss</source>
</trans-unit>
<trans-unit id="++CODE++8a2ada67a303fe2602331dc153b30259b92e7cc2d741f8d5955d8af906ef016a">
<source xml:lang="en">Displays the data type name for the column</source>
</trans-unit>
<trans-unit id="++CODE++85297edc780e231f74a5f8ed6ec249358dfae002e468ef4fdf8e568b95e27c94">
<source xml:lang="en">Displays the description of the column</source>
</trans-unit>
<trans-unit id="++CODE++7bba5bcc44de61b37dcadb5824fac7130483b749da0c5e9eea5e02765e06e37d">
<source xml:lang="en">Displays the unified data type (including length, scale and precision) for the column</source>
</trans-unit>
<trans-unit id="++CODE++464c4ffd019e1e9691dcf0537c797353ef2b1c1d4833d3d463e5b74ae4547344">
<source xml:lang="en">Edit</source>
</trans-unit>
@ -282,12 +372,18 @@
<trans-unit id="++CODE++6051d2070e8e51a99adfa6b3f5171cfa92107943f46417bcd51a8f5e995c881f">
<source xml:lang="en">End IP Address</source>
</trans-unit>
<trans-unit id="++CODE++1a77d555bedbf97481907d505c8c8ba64d32d3525b77122e16178dd4054c3c93">
<source xml:lang="en">Ends With</source>
</trans-unit>
<trans-unit id="++CODE++b35ebaaf32f469f2fa86b0b2fb67e6f51fae3fb8e6ceaeaea97c2696321a8ee4">
<source xml:lang="en">Enter new column width</source>
</trans-unit>
<trans-unit id="++CODE++f939ae3d30c69e332a36892f70d401d457e6993f056b8d0af3fe3d736821f5a1">
<source xml:lang="en">Equals</source>
</trans-unit>
<trans-unit id="++CODE++54a0e8c17ebb21a11f8a25b8042786ef7efe52441e6cc87e92c67e0c4c0c6e78">
<source xml:lang="en">Error</source>
</trans-unit>
<trans-unit id="++CODE++f251a7b2d632de7a4122dafe6fd4a9e984d632ffe0c1e71591e5e253ea9fda11">
<source xml:lang="en">Error Message: </source>
</trans-unit>
@ -302,6 +398,12 @@
<trans-unit id="++CODE++480311d3f925f85184b69381dc5f05bb2607e6beb8d354ffe58276a0cd1dd5d9">
<source xml:lang="en">Error connecting to: </source>
</trans-unit>
<trans-unit id="++CODE++f6d7eb5fe821427ad07a3bf9a3cc35423ddc3ccd3a745b1f09584fbf26f377fe">
<source xml:lang="en">Error loading designer</source>
</trans-unit>
<trans-unit id="++CODE++6d89c16c7cf3f832b29fe1d181d420d4a583f93bb02e63fdfa266c33b6b3fcaf">
<source xml:lang="en">Error loading preview</source>
</trans-unit>
<trans-unit id="++CODE++619d1a6dc49f043552f7b8d14e6483de4a2caf1c8270d6168a642c8eccc3a752">
<source xml:lang="en">Error occurred opening content in editor.</source>
</trans-unit>
@ -336,6 +438,9 @@
<trans-unit id="++CODE++bd705ebabe1919a636a0e09b2ee27d43a5aba05d645cc0339451e54b37f42bd6">
<source xml:lang="en">Execution Plan</source>
</trans-unit>
<trans-unit id="++CODE++c67415bcff328a59fd399e2a7ca9691e0044192fb7480ae501644339965d046d">
<source xml:lang="en">Expression</source>
</trans-unit>
<trans-unit id="++CODE++031a8f0f659df890dfd53c92e45295b0f14c997185bae46e168831e403b273f7">
<source xml:lang="en">Failed</source>
</trans-unit>
@ -362,6 +467,9 @@
<trans-unit id="++CODE++283dc9bd4f27ff0efed1b3ac27910746f64f860e2e0c2240f9723ff02c1dc29c">
<source xml:lang="en">Failed to save results. </source>
</trans-unit>
<trans-unit id="++CODE++103456e9e42f094edd7aa359537505ad54de66ac826f5bddd03f9f569fbace89">
<source xml:lang="en">Filter Settings</source>
</trans-unit>
<trans-unit id="++CODE++051ab9f3bd7362945f1e2adc7c118c48d4286a3e181158b32e8e87f915103e73">
<source xml:lang="en">Find Node</source>
</trans-unit>
@ -381,6 +489,24 @@
<trans-unit id="++CODE++3a5a47667104807574cb0875e1ad13546429f3ed63efe6b4bddee62fe1f4cf5b">
<source xml:lang="en">Firewall rule successfully created.</source>
</trans-unit>
<trans-unit id="++CODE++52742c9dc235ecbc2154d3bef091d1e39dd0b8b542ebac8031331a146b83242d">
<source xml:lang="en">For numeric data, the maximum number of decimal digits that can be stored in this database object to the right of decimal point.</source>
</trans-unit>
<trans-unit id="++CODE++20b04b0eb9264d54736120dae88c712700ee14a95803823187961e630998a7fc">
<source xml:lang="en">For numeric data, the maximum number of decimal digits that can be stored in this database object.</source>
</trans-unit>
<trans-unit id="++CODE++2390e8502ba64cd13706dd2af52d9983efe51a28984739601b0b86fbf7c65904">
<source xml:lang="en">Foreign Column</source>
</trans-unit>
<trans-unit id="++CODE++43aaa008cb8b129bc33f70e1c70317da8a00fd95e83728587f3a84053b4df2a1">
<source xml:lang="en">Foreign Key</source>
</trans-unit>
<trans-unit id="++CODE++7d30023ced5527cc9061c41e18c832bba55267935cbfc5c45a68dbf5dcc5a310">
<source xml:lang="en">Foreign Keys</source>
</trans-unit>
<trans-unit id="++CODE++343460cabeff0fb48d3eaab8a7b7cec8ab6533656b987b607002e6fae59daa8b">
<source xml:lang="en">Foreign Table</source>
</trans-unit>
<trans-unit id="++CODE++936af734b4badd8602cb27237f8dea0fd3950e12b5bab278565babc15e854136">
<source xml:lang="en">Found pending reconnect promise for uri {0}, failed.</source>
<note>{0} is the uri</note>
@ -389,9 +515,21 @@
<source xml:lang="en">Found pending reconnect promise for uri {0}, waiting.</source>
<note>{0} is the uri</note>
</trans-unit>
<trans-unit id="++CODE++e7789e4d6916633a7461743194a10f2bc4d20b06c2e329b35c7a2da87aa8cbae">
<source xml:lang="en">Generate Script</source>
</trans-unit>
<trans-unit id="++CODE++bccb449867268397632519e5695a6bb611a30529b735cac4f7d5ecbaee80e785">
<source xml:lang="en">Getting definition ...</source>
</trans-unit>
<trans-unit id="++CODE++e20bd7d7e901d3e58a8f309f390dfb1a743fd3108eed0db8e70c73c9ffe1c23d">
<source xml:lang="en">Go there</source>
</trans-unit>
<trans-unit id="++CODE++774b3dff4a0e941fad0742c915bd93885c9cb15f769f2c92c2ea384b69780f51">
<source xml:lang="en">Greater Than</source>
</trans-unit>
<trans-unit id="++CODE++8885e80bb197b22bc702906ef86b149ad49d258c5cb14b09227c19ee4f01061e">
<source xml:lang="en">Greater Than Or Equals</source>
</trans-unit>
<trans-unit id="++CODE++b79cac926e0b2e347e72cc91d5174037c9e17ae7733fd7bdb570f71b10cd7bfc">
<source xml:lang="en">Help</source>
</trans-unit>
@ -404,6 +542,12 @@
<trans-unit id="++CODE++c1f88e9d6c4145cf0530ae020155384d5688d70ed82a07a35d783bbc4b32238c">
<source xml:lang="en">In progress</source>
</trans-unit>
<trans-unit id="++CODE++39c3be1198a2fddf18d03608348d9cfaf8823d2dda4d5ff13fdb851bd15d29ea">
<source xml:lang="en">Index</source>
</trans-unit>
<trans-unit id="++CODE++90b901a30c3f089e10d82e1b842bbdc736a36b536a19d207b36a8e7be1904dcb">
<source xml:lang="en">Indexes</source>
</trans-unit>
<trans-unit id="++CODE++afe3d8a0f4733dcd43ec5b17d8c6d8d3ec7e53c511f1ad49d1168ea289bdd055">
<source xml:lang="en">Integrated</source>
</trans-unit>
@ -416,12 +560,24 @@
<trans-unit id="++CODE++b6b50087a99bf4427265eff9dd813914f1ceb8c55260fa6e7075f9c89fcd45d7">
<source xml:lang="en">Invalid column width</source>
</trans-unit>
<trans-unit id="++CODE++666067dd376e5d4553b8fd554f855855819ad213ae825022d2a32dfa28431115">
<source xml:lang="en">Issues</source>
</trans-unit>
<trans-unit id="++CODE++db1a21a0bc2ef8fbe13ac4cf044e8c9116d29137d5ed8b916ab63dcb2d4290df">
<source xml:lang="en">JSON</source>
</trans-unit>
<trans-unit id="++CODE++a3c13b491573b0d54bf743caf0f5d59d5a791c42ae1072f16bb941be925fae18">
<source xml:lang="en">Keys for token cache could not be saved in credential store, this may cause Microsoft Entra Id access token persistence issues and connection instabilities. It&apos;s likely that SqlTools has reached credential storage limit on Windows, please clear at least 2 credentials that start with &quot;Microsoft.SqlTools|&quot; in Windows Credential Manager and reload.</source>
</trans-unit>
<trans-unit id="++CODE++adc95605a1b30c73959fbaf21e60f9723efe855c482fa336a957924d4ea0a08b">
<source xml:lang="en">Length</source>
</trans-unit>
<trans-unit id="++CODE++ab7e3aa3d0d8c78763c986b6a831726ff623b195a38a8d4b1191976c0becf72e">
<source xml:lang="en">Less Than</source>
</trans-unit>
<trans-unit id="++CODE++a408b91cd1b01aac0b9fa7eec7fafac233eb172b0aafcdf013d88575fac35c1f">
<source xml:lang="en">Less Than Or Equals</source>
</trans-unit>
<trans-unit id="++CODE++d05f53bafc473abafc1af3b592a9186f7c8b2579999c953b6f3d9f9450c43f50">
<source xml:lang="en">Line {0}</source>
<note>{0} is the line number</note>
@ -429,6 +585,12 @@
<trans-unit id="++CODE++dc380888c4e2c7762212480ff86eb39150ec70b45009c33bc6adcbd0041384b1">
<source xml:lang="en">Loading</source>
</trans-unit>
<trans-unit id="++CODE++10a371b8dc47cdf83c4cd7f926daf76305a6b52311a69b3087d744151dc53501">
<source xml:lang="en">Loading Table Designer</source>
</trans-unit>
<trans-unit id="++CODE++c47aaf844e09d0c6bd516bf7b71a31e66eac808241c7ec609c6c74c54908daa4">
<source xml:lang="en">Loading table designer</source>
</trans-unit>
<trans-unit id="++CODE++aaaeb8d7872b0c49ed19d951314516d2dcd84ca23411320f05fac3d87bac8a32">
<source xml:lang="en">MSSQL</source>
</trans-unit>
@ -469,6 +631,33 @@
<source xml:lang="en">Microsoft Entra account {0} successfully added.</source>
<note>{0} is the account name</note>
</trans-unit>
<trans-unit id="++CODE++b58330ac25057a441365f4f4f1be20daba2d6d940142c891231e0eac66843ff4">
<source xml:lang="en">Move Down</source>
</trans-unit>
<trans-unit id="++CODE++1359626e7b6964345896285446db7977e67469251bb0cc52808db2a85ed940c1">
<source xml:lang="en">Move Up</source>
</trans-unit>
<trans-unit id="++CODE++dcd1d5223f73b3a965c07e3ff5dbee3eedcfedb806686a05b9b3868a2c3d6d50">
<source xml:lang="en">Name</source>
</trans-unit>
<trans-unit id="++CODE++ad4811485a0a0f3f000987d581730b04c0bf33a9d4ccf59a9ff1c127b33d76d1">
<source xml:lang="en">Name of the primary key.</source>
</trans-unit>
<trans-unit id="++CODE++e7d029a3c1b85e562db8e25ceb52958e3c3da9e6e50b95ebf95f3fae85091a15">
<source xml:lang="en">New Check Constraint</source>
</trans-unit>
<trans-unit id="++CODE++5a59551b2622ee0d2767d9bbc3d03aa227824d88c6b25ac233cfb2a98684512c">
<source xml:lang="en">New Column</source>
</trans-unit>
<trans-unit id="++CODE++4a00fefe019ef43393da250ba4b62d7b6af849a1acac99b1192ffbeda8828fe7">
<source xml:lang="en">New Column Mapping</source>
</trans-unit>
<trans-unit id="++CODE++b71586503f1694b5328fa16ed600eb0d20d4d9608dfb54f44ae97fe4ac43f0bf">
<source xml:lang="en">New Foreign Key</source>
</trans-unit>
<trans-unit id="++CODE++30a5aebdb4a5faa3b927c90ef856e84e039707488be19e760b3701f24889875d">
<source xml:lang="en">New Index</source>
</trans-unit>
<trans-unit id="++CODE++6334507f512e52b67d0a5a0fb392e35e5d3acc29acdce7218f66b6199150f589">
<source xml:lang="en">New Microsoft Entra account could not be added.</source>
</trans-unit>
@ -487,6 +676,9 @@
<trans-unit id="++CODE++87a122216f22b55fd29964cf75c886ef5da5cd8369e2a6e24c73ec0ad22227ba">
<source xml:lang="en">No connection was found. Please connect to a server first.</source>
</trans-unit>
<trans-unit id="++CODE++3b41ba9c7cb8c5d6530c12eec5000c4e2ad0c48b2d4b9149a3ef6d2a23802819">
<source xml:lang="en">No data</source>
</trans-unit>
<trans-unit id="++CODE++c933cd0d45861a20699df513967542bc9b448f409d362d9bec4e7443dd96f403">
<source xml:lang="en">No need to refresh Microsoft Entra acccount token for connection {0} with uri {1}</source>
<note>{0} is the connection id
@ -495,18 +687,42 @@
<trans-unit id="++CODE++dc937b59892604f5a86ac96936cd7ff09e25f18ae6b758e8014a24c7fa039e91">
<source xml:lang="en">None</source>
</trans-unit>
<trans-unit id="++CODE++58601e3ffba5990d1be4db9f2bcc6107f9a72949aabd8f68f79bcb2c92195b5f">
<source xml:lang="en">Not Between</source>
</trans-unit>
<trans-unit id="++CODE++bfccbdda37b86c50ee3c10c461afc9fcc2854ca2d53d33b9bb079798a4f0cf21">
<source xml:lang="en">Not Contains</source>
</trans-unit>
<trans-unit id="++CODE++1035e37a14f3bc0faf8a937fddf3a6ca0ef9b7ad40aa1de814f0865e044eeda2">
<source xml:lang="en">Not Ends With</source>
</trans-unit>
<trans-unit id="++CODE++2abe6ce3689dddb31a75faaafb1a7293649d60f93bff0e48a87e7d5ddd7f2530">
<source xml:lang="en">Not Equals</source>
</trans-unit>
<trans-unit id="++CODE++544330f40460cbf3595ddb51445d81c643d5cd9dc72d601db887c01169b5f388">
<source xml:lang="en">Not Starts With</source>
</trans-unit>
<trans-unit id="++CODE++ba35f0c47d862763dafa955d6716942f79b8bfe1d01d5968520db6f9ba665f6f">
<source xml:lang="en">Not started</source>
</trans-unit>
<trans-unit id="++CODE++6091a3057f7b1b8140c1ad2fc9232cc4d483a484667f76fe8bb305d77ca3deb1">
<source xml:lang="en">Number of Rows Read</source>
</trans-unit>
<trans-unit id="++CODE++565339bc4d33d72817b583024112eb7f5cdf3e5eef0252d6ec1b9c9a94e12bb3">
<source xml:lang="en">OK</source>
</trans-unit>
<trans-unit id="++CODE++501ec8c3629bcdcd52b9d7895c90d04b0c0b969f1134ba024efe021f0a25d867">
<source xml:lang="en">Object Explorer Filter</source>
</trans-unit>
<trans-unit id="++CODE++ca7981b46ecf2c1787b6d76d81d9fd7fa0ca95842e2fcc2a452869891a9334d1">
<source xml:lang="en">Off</source>
</trans-unit>
<trans-unit id="++CODE++08cc7dbe92d634292815733fbf6b34fba13792fc61a838f93bcaf5fc639b12ee">
<source xml:lang="en">On Delete Action</source>
</trans-unit>
<trans-unit id="++CODE++53dbddd7bcdf5a51afae1447f034e76d78722d20c1d6d62002c00e19f68ea9b2">
<source xml:lang="en">On Update Action</source>
</trans-unit>
<trans-unit id="++CODE++ed077f3d8125d60dca1979c7133601bd187d47c73ed9975028f677e49e709942">
<source xml:lang="en">Open</source>
</trans-unit>
@ -516,12 +732,18 @@
<trans-unit id="++CODE++404eb1204c0e313b45f63c32657b2cabf3f3930b7a731969c82b5bc3061311ff">
<source xml:lang="en">Open Query History</source>
</trans-unit>
<trans-unit id="++CODE++944c9ff52cb5d872b8765cfd8e22debf3ca4b887a094ed5bce64cd783279951f">
<source xml:lang="en">Open Xml</source>
<trans-unit id="++CODE++458f7bdeed472d6583d8b0e14f2535e896f301136ee1ea3c63fdbf0845407225">
<source xml:lang="en">Open XML</source>
</trans-unit>
<trans-unit id="++CODE++e0af5c0bc2457475ab3c6e78ea06374a904469684daf6bffa229ac990b21aca3">
<source xml:lang="en">Open in new tab</source>
</trans-unit>
<trans-unit id="++CODE++ea56aa4cb881e4c3d61d84b95881280b4c10519222fcfe40febcbd4b2d548333">
<source xml:lang="en">OpenSSL version &gt;=1.0.1 is required to connect.</source>
</trans-unit>
<trans-unit id="++CODE++291101a07fe980e93b900ae85c9eb824f9e7e93d0d754be7440b9386b615cad7">
<source xml:lang="en">Operator</source>
</trans-unit>
<trans-unit id="++CODE++da53ba1a285ffae9c6528e235b57336fa85b4f05e9fc00a51ee922069c3d9865">
<source xml:lang="en">Optional (False)</source>
</trans-unit>
@ -537,6 +759,16 @@
<trans-unit id="++CODE++b0f439de4ac489dfe75bf62e7fb55c9c993851f6f462fbbacae37851a6cad588">
<source xml:lang="en">Password (SQL Login)</source>
</trans-unit>
<trans-unit id="++CODE++71f0edbc866bcd836e06eefc36556b0e6a3552f2d422dc8bc12bddd51e3b5a8e">
<source xml:lang="en">Path: {0}</source>
<note>{0} is the path of the node in the object explorer</note>
</trans-unit>
<trans-unit id="++CODE++b5d65f0ae389b60297c51acb9d3f3ee1e5b846deeb84a90fd69ccdfadca7c331">
<source xml:lang="en">Precision</source>
</trans-unit>
<trans-unit id="++CODE++9d13699b657fe91178f41ecf87e9c11095306c7b62e26f7e7a1b019df9ca50b1">
<source xml:lang="en">Preview Database Updates</source>
</trans-unit>
<trans-unit id="++CODE++a89f61eb88c67866f6b2666a2e7f19b6fa1c97ca8330b81f848895bcc3594a3f">
<source xml:lang="en">Previous pending reconnect promise for uri {0} is rejected with error {1}, will attempt to reconnect if necessary.</source>
<note>{0} is the uri
@ -546,6 +778,12 @@
<source xml:lang="en">Previous pending reconnection for uri {0}, succeeded.</source>
<note>{0} is the uri</note>
</trans-unit>
<trans-unit id="++CODE++92022c2f45b6a9ba92c51438e6fed444d69673e4bd6c529e3ea8f0a8bfe1e969">
<source xml:lang="en">Primary Key</source>
</trans-unit>
<trans-unit id="++CODE++a0de89c19964a6454c6d6b4f4205b8c8fcb6c1bfe9370b6d3183226ce8009141">
<source xml:lang="en">Primary Key Columns</source>
</trans-unit>
<trans-unit id="++CODE++a423b47777783386516c79baa19b0dfcd12cb40e4fba79348ad14ab0169402cd">
<source xml:lang="en">Profile Name</source>
</trans-unit>
@ -558,10 +796,22 @@
<trans-unit id="++CODE++c7b24e72fefeade2fc1706604bb5c2ee848b055ed154428128c10d5020549a7a">
<source xml:lang="en">Profile removed successfully</source>
</trans-unit>
<trans-unit id="++CODE++ae43692b2a310b8ed2443d2b7d2a3e4cf0b6d73115badd72831b3d22381f235f">
<source xml:lang="en">Properties</source>
</trans-unit>
<trans-unit id="++CODE++40040cb181f7f0ee5add2b52e8467c6652477f7ce12af39fe380b5084b64f4fe">
<source xml:lang="en">Property</source>
</trans-unit>
<trans-unit id="++CODE++7c68cc7494a11be986cf0d4ac8e2acb67d5aa67b35151c2435cb1c51ccd060d8">
<source xml:lang="en">Provider &apos;{0}&apos; does not have a Microsoft resource endpoint defined.</source>
<note>{0} is the provider</note>
</trans-unit>
<trans-unit id="++CODE++859390eb495b2ead7f05f0f799546c71435b2db31dbe082adecc3426fffc3391">
<source xml:lang="en">Publish</source>
</trans-unit>
<trans-unit id="++CODE++10209ed1750a4b5c09b80ea470ed45083d8d1ad3d1da877d160d9ab61a5031fc">
<source xml:lang="en">Publishing Changes</source>
</trans-unit>
<trans-unit id="++CODE++9e83dc6d2db272ac27cc875b994f834b62b7202a49b69e885f8f4e8f9c29a452">
<source xml:lang="en">Query executed</source>
</trans-unit>
@ -571,14 +821,17 @@
<trans-unit id="++CODE++9bb19ac86101a6dfe00ba121dc8fab54c216992ef8d061c9cf27bd93a4424a91">
<source xml:lang="en">Query succeeded</source>
</trans-unit>
<trans-unit id="++CODE++ff833ae4350e6cf5bc3d5df476a36393719be6350d9a39b7f701a7dc05279dd8">
<source xml:lang="en">Query {0}: Query cost (relative to the script): {1}</source>
<trans-unit id="++CODE++9f24e982799f47ef97760b8fbb95ce6c89390fba37aa7fe9b6314f69aaa691ea">
<source xml:lang="en">Query {0}: Query cost (relative to the script): {1}%</source>
<note>{0} is the query number
{1} is the query cost</note>
</trans-unit>
<trans-unit id="++CODE++83b794145c0cc3f560cb6dfb6b5bcf7afac4dba15e5c6dbc54d103dae029fec6">
<source xml:lang="en">Read more</source>
</trans-unit>
<trans-unit id="++CODE++705aa26f40f31a71c622836f9a913bf837817f54e45133215a5d222489e6a7c8">
<source xml:lang="en">Recent Connections</source>
</trans-unit>
<trans-unit id="++CODE++703f1ae8b7cdb3525cdab9ea694ab27b1b9e4337f0b2ca32f152f7f9a6e2f9d5">
<source xml:lang="en">Recent connections list cleared</source>
</trans-unit>
@ -630,6 +883,18 @@
<trans-unit id="++CODE++bae1da28225af71a125385224716f5ff7870573e6c01494c597e8ed4168b12e3">
<source xml:lang="en">Save results command cannot be used with multiple selections.</source>
</trans-unit>
<trans-unit id="++CODE++f102986b39effb31080ae442f61febe7ed58df1515c0711ccfadfe0311ccec81">
<source xml:lang="en">Scale</source>
</trans-unit>
<trans-unit id="++CODE++07b091a3fdc4e4c03cd047b5264e61241f20fe8dbc36a4c796d46cd8dc3e7d03">
<source xml:lang="en">Schema</source>
</trans-unit>
<trans-unit id="++CODE++cce7c24ebb0a14bc98b7d6a3f18ddfe9c893e65adb1a599321b3e0eca3515490">
<source xml:lang="en">Script As Create</source>
</trans-unit>
<trans-unit id="++CODE++3a4a2e94c1227e991b2d55800b114ce9ef01970894efa5dade81ab8f14adda8b">
<source xml:lang="en">Script as CREATE</source>
</trans-unit>
<trans-unit id="++CODE++ebe0dbee443b4562c7925a01e3bc69a3d5d0a3b0e8b3e11041c69fa067b65ef7">
<source xml:lang="en">Select a tenant</source>
</trans-unit>
@ -660,6 +925,9 @@
<trans-unit id="++CODE++3e27420fb58defcc5b721d6bfdbb9c092230a888d571821f747f7bffec92f17c">
<source xml:lang="en">Server name or ADO.NET connection string</source>
</trans-unit>
<trans-unit id="++CODE++5e9f98120dbe568255ee059f39671686982b113d4e917b6d6faf149918c81709">
<source xml:lang="en">Severity</source>
</trans-unit>
<trans-unit id="++CODE++8c6f0777a59f6d55efb68be5323e48061f19e0b2c036c9f34f3ea7655eeaead2">
<source xml:lang="en">Show MSSQL output</source>
</trans-unit>
@ -675,6 +943,12 @@
<trans-unit id="++CODE++2a2c6072cca49b7f2056d66f738d53593bce3004d1291d736ea9a69e58babae8">
<source xml:lang="en">Sign in to your Azure subscription with a device code. Use this in setups where the Sign In command does not work</source>
</trans-unit>
<trans-unit id="++CODE++1e49ea47266ab1130ffc9be417fa6eb62da7299641f30a76e728fe983c25f29d">
<source xml:lang="en">Specifies whether the column is included in the primary key for the table.</source>
</trans-unit>
<trans-unit id="++CODE++ed17e62be4222e6fa3890918aee4885848f3e87ee14bc9b5dbe65e603173f26b">
<source xml:lang="en">Specifies whether the column may have a NULL value.</source>
</trans-unit>
<trans-unit id="++CODE++a49eb416daf711062abb036ea09b46cbe49f513082db1ef699e94ddcf35adc42">
<source xml:lang="en">Start IP Address</source>
</trans-unit>
@ -688,6 +962,9 @@
<trans-unit id="++CODE++47d62b3ce92021fa331252ba82176c2a4ccb592c2264bd58ec74e5d1b722c98e">
<source xml:lang="en">Started saving results to </source>
</trans-unit>
<trans-unit id="++CODE++72927b6fdb5388115d478bb5e0e69c203231f35ad2e0721d77750626ea4fe4db">
<source xml:lang="en">Starts With</source>
</trans-unit>
<trans-unit id="++CODE++0035c67b91c2dd1e5f7a1fd9010b07ee0cdc93e578c2baf656dfc411a80f4b78">
<source xml:lang="en">Subtree Cost</source>
</trans-unit>
@ -709,6 +986,9 @@
<trans-unit id="++CODE++5b483648ad7b3afcd20f3ccef6fdc7471e39d5a8c9bb30697cba5f82c4ff8dc1">
<source xml:lang="en">Switch to MSAL</source>
</trans-unit>
<trans-unit id="++CODE++529667eb9a218f074e24ec63181bb6b3bd4e5ea744e64f71262b6323251ed743">
<source xml:lang="en">Table name</source>
</trans-unit>
<trans-unit id="++CODE++e23969d284c3424c8014c6e5b1b85ebc275bc5c74321e7677a21d023e6ea154c">
<source xml:lang="en">Tenant</source>
</trans-unit>
@ -718,12 +998,84 @@
<trans-unit id="++CODE++3db7232b2e9f0b74bad366312879cd89ee7bd3e6c5b737f358b7897907c6ab39">
<source xml:lang="en">Tenant ID is required</source>
</trans-unit>
<trans-unit id="++CODE++c02977b07ec93816f236c57b4c30d4544904e87e0a43a1daf344c229594320b9">
<source xml:lang="en">Test Connection</source>
</trans-unit>
<trans-unit id="++CODE++90c8505baad739c0925471e0d594ba9d83f84d3a96dbdfa16a47ae7a3ad95d91">
<source xml:lang="en">Testing connection profile...</source>
</trans-unit>
<trans-unit id="++CODE++3eacf5cf678e2285cae1276d29f034aa0e7ceb3f8940239c1d67a2d486649719">
<source xml:lang="en">The behavior when a user tries to delete a row with data that is involved in a foreign key relationship.</source>
</trans-unit>
<trans-unit id="++CODE++1a4205e9f5cc50eaf70719b64956352b74a99badba266027a6244def0d016b73">
<source xml:lang="en">The behavior when a user tries to update a row with data that is involved in a foreign key relationship.</source>
</trans-unit>
<trans-unit id="++CODE++4002a5b20dd0c7a8caf9764ba024343e8f87e2ba8221aaeae4c5112d1d7bb4ed">
<source xml:lang="en">The columns of the index.</source>
</trans-unit>
<trans-unit id="++CODE++f229c94b4c9b8ecfa1096d1daf79194e84616c49df8fb6e229fa944592ff373e">
<source xml:lang="en">The description of the check constraint.</source>
</trans-unit>
<trans-unit id="++CODE++f307f68f2f552562e371f39fe52ef5b9f6eba2e13a61cd2d1e560e9991b86114">
<source xml:lang="en">The description of the foreign key.</source>
</trans-unit>
<trans-unit id="++CODE++48e857284768923e885f8631cb33e52313c21cd97d4b95b651b1b5227789cfa0">
<source xml:lang="en">The description of the index.</source>
</trans-unit>
<trans-unit id="++CODE++4ed30ce390b4a87aa521240a8313735faff4c4cb4df0c01292ffdaf5b9a44c58">
<source xml:lang="en">The description of the primary key.</source>
</trans-unit>
<trans-unit id="++CODE++ff83ab307bf5543897d2c5781d880385ba86a704904fb08dc5c67c990688d5ec">
<source xml:lang="en">The expression defining the check constraint.</source>
</trans-unit>
<trans-unit id="++CODE++d160b49baa7c6e4e8b95a21a984b19fda338b9d47a01d61c2d7445ed29cf174e">
<source xml:lang="en">The first value must be less than the second value for the {0} operator in the {1} filter</source>
<note>{0} is the operator for the filter
{1} is the name of the filter</note>
</trans-unit>
<trans-unit id="++CODE++10dc5228a8a16a8eb753ca437fd81cd632ca4b12be41a33403e6614e46c4167e">
<source xml:lang="en">The first value must be set for the {0} operator in the {1} filter</source>
<note>{0} is the operator for the filter
{1} is the name of the filter</note>
</trans-unit>
<trans-unit id="++CODE++fcd9241097659a9ae58a06bd9b762b5aded99a3f82d97e73e75279b098e00c6d">
<source xml:lang="en">The mapping between foreign key columns and primary key columns.</source>
</trans-unit>
<trans-unit id="++CODE++ee33dcb49174e212fabe894df8373991cebe8d617d56b472934c7dcea6335b5b">
<source xml:lang="en">The maximum length (in characters) that can be stored in this database object.</source>
</trans-unit>
<trans-unit id="++CODE++c368a965891e9479b44218cb42c8cddde404740e364b53367e897dcb17ef1d6b">
<source xml:lang="en">The name of the check constraint.</source>
</trans-unit>
<trans-unit id="++CODE++1f1828f6aa124ec76ef4d972c0dc128052fd3b8b5fa4cefd9d560695e878ecf8">
<source xml:lang="en">The name of the column object.</source>
</trans-unit>
<trans-unit id="++CODE++4b7c298367264cb30b7b914a70b1a21e86cc7685024ae618a0d0cf43626afe54">
<source xml:lang="en">The name of the column.</source>
</trans-unit>
<trans-unit id="++CODE++20b946c00bb4f007424d33a637029256f737bb0ff32c7de3b2a189e4423a4ec9">
<source xml:lang="en">The name of the foreign key.</source>
</trans-unit>
<trans-unit id="++CODE++644a28f160d2df093fab1a8c94e5176f21c1af3bee1915315edd409d14397021">
<source xml:lang="en">The name of the index.</source>
</trans-unit>
<trans-unit id="++CODE++289db14dbc3d213c4ac28f356bcfc37eb02f473e07ee63bcea2fa7075c888822">
<source xml:lang="en">The name of the table object.</source>
</trans-unit>
<trans-unit id="++CODE++13549c97f0b3baa43655bd41e05e3bb60918ded05df9e7e94186ecc6ba53c3d1">
<source xml:lang="en">The recent connections list has been cleared but there were errors while deleting some associated credentials. View the errors in the MSSQL output channel.</source>
</trans-unit>
<trans-unit id="++CODE++c9d2c41f4eeba094c6db66ab88d3c5190e34865d80fe230483b6fdcaddf79e8a">
<source xml:lang="en">The schema that contains the table.</source>
</trans-unit>
<trans-unit id="++CODE++ea13943c4f06ddf0a81173991d20e8cf8252b636b94c0c2476e58098d9fbc1f3">
<source xml:lang="en">The second value must be set for the {0} operator in the {1} filter</source>
<note>{0} is the operator for the filter
{1} is the name of the filter</note>
</trans-unit>
<trans-unit id="++CODE++d7f9cfdbfc45384b7521ed4b8082d476a2d3cae5cbb8c57eec64003513cacbf2">
<source xml:lang="en">The table which contains the primary or unique key column.</source>
</trans-unit>
<trans-unit id="++CODE++2b8198974f44b4a37d366cb6535153e3646f2c9de308f0ca05bf90513b0a4630">
<source xml:lang="en">This setting requires Visual Studio Code to be relaunched, please reload Visual Studio Code.</source>
</trans-unit>
@ -743,12 +1095,18 @@
<source xml:lang="en">Total execution time: {0}</source>
<note>{0} is the elapsed time</note>
</trans-unit>
<trans-unit id="++CODE++baaddf70fb5d432b8bd948ef91d6f910124a6d138edae4d5f000c4610ddc8eae">
<source xml:lang="en">Type</source>
</trans-unit>
<trans-unit id="++CODE++e395097d9cde221cdb9af8b04e1073d0d3394439fce660d1c954d012cdeae6c1">
<source xml:lang="en">Unable to execute the command while the extension is initializing. Please try again later.</source>
</trans-unit>
<trans-unit id="++CODE++30f9be31de0326b58d28b9578bd91145abf4047074018ac47bc845f960328167">
<source xml:lang="en">Unable to expand. Please check logs for more information.</source>
</trans-unit>
<trans-unit id="++CODE++6f32c6efd3fd051f5df8f5a6926828722e2734a8b2138751abf9363a674550bd">
<source xml:lang="en">Update Database</source>
</trans-unit>
<trans-unit id="++CODE++92294188e79b2a13584eb3e6120f971c94ada2a387f3199a4cd3cb17039f9d37">
<source xml:lang="en">Updating IntelliSense...</source>
</trans-unit>
@ -764,6 +1122,9 @@
<trans-unit id="++CODE++bb6e451b4ca453ef7b93d4a89b702cde206029b5c57a46ac64072d7e909018c4">
<source xml:lang="en">User name is required</source>
</trans-unit>
<trans-unit id="++CODE++8e37953d23daca5ff01b8282c33f4e0a2152f1d1885f94c06418617e3ee1d24e">
<source xml:lang="en">Value</source>
</trans-unit>
<trans-unit id="++CODE++15435b311c9371437109bd5323292504915507b034803118517fee44e9547a3c">
<source xml:lang="en">View More</source>
</trans-unit>
@ -836,6 +1197,27 @@
<trans-unit id="++CODE++d4781f8681d947d6d8eb589d9a93c7bd093110ab1b826da373b7e1e6b6cf080f">
<source xml:lang="en">{0} (filtered)</source>
</trans-unit>
<trans-unit id="++CODE++e3620e8a37371c6057d768faed05a7608c6e5ee783372a58b137b047300e8b7a">
<source xml:lang="en">{0} issue</source>
<note>{0} is the number of issues</note>
</trans-unit>
<trans-unit id="++CODE++b770b7713326a104665ea604e4a6c8c1e7d9d33d797359c3f118418c365c4bdc">
<source xml:lang="en">{0} issues</source>
</trans-unit>
<trans-unit id="++CODE++4960928686dec57850ef0fde437021e4bec60d6d0fcc3e196448bb01c88d3920">
<source xml:lang="en">{0} issues</source>
<note>{0} is the number of issues</note>
</trans-unit>
<trans-unit id="++CODE++e29f55f346b08b76ddf9633f8d991e9cc16f8f201f837052b3e59e681ba2dbda">
<source xml:lang="en">{0} {1} issue</source>
<note>{0} is the tab name
{1} is the number of issues</note>
</trans-unit>
<trans-unit id="++CODE++b3a182c894c403e6b24bcc5dfc3ba0eeab9b2380519d82944789b5ffa76b1235">
<source xml:lang="en">{0} {1} issues</source>
<note>{0} is the tab name
{1} is the number of issues</note>
</trans-unit>
<trans-unit id="++CODE++fbf6567d7b396892abbe6cccf81dca280649e099b853b805be1beb6af53d9229">
<source xml:lang="en">{0}. {1}</source>
<note>{0} is the status

Просмотреть файл

@ -464,25 +464,4 @@ export let additionalParameters = l10n.t('Additional parameters');
export let connect = l10n.t('Connect');
export let parameters = l10n.t('Parameters');
export let loading = l10n.t('Loading');
export let metric = l10n.t('Metric');
export let actualElapsedTime = l10n.t('Actual Elapsed Time');
export let actualElapsedCpuTime = l10n.t('Actual Elapsed CPU Time');
export let cost = l10n.t('Cost');
export let subtreeCost = l10n.t('Subtree Cost');
export let actualNumberOfRows = l10n.t('Actual Number of Rows For All Executions');
export let numRowsRead = l10n.t('Number of Rows Read');
export let off = l10n.t('Off');
export let findNodes = l10n.t('Find Nodes');
export let equals = l10n.t('Equals');
export let contains = l10n.t('Contains');
export let savePlan = l10n.t('Save Plan');
export let openXml = l10n.t('Open Xml');
export let openQuery = l10n.t('Open Query');
export let zoomIn = l10n.t('Zoom In');
export let zoomOut = l10n.t('Zoom Out');
export let zoomToFit = l10n.t('Zoom to Fit');
export let customZoom = l10n.t('Custom Zoom');
export let findNode = l10n.t('Find Node');
export let highlightOps = l10n.t('Highlight Expensive Operation');
export let toggleTooltips = l10n.t('Toggle Tooltips');
export let executionPlan = l10n.t('Execution Plan');

Просмотреть файл

@ -6,7 +6,6 @@
import * as vscode from "vscode";
import { ReactWebviewPanelController } from "./reactWebviewController";
import * as ep from "../reactviews/pages/ExecutionPlan/executionPlanInterfaces";
import * as LocalizedConstants from "../constants/locConstants";
import { homedir } from "os";
import { exists } from "../utils/utils";
import UntitledSqlDocumentService from '../controllers/untitledSqlDocumentService';
@ -33,7 +32,6 @@ export class ExecutionPlanWebviewController extends ReactWebviewPanelController<
{
sqlPlanContent: executionPlanContents,
theme: vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.Dark ? "dark" : "light",
localizedConstants: LocalizedConstants,
loadState: ApiStatus.Loading,
executionPlan: undefined,
executionPlanGraphs: [],

Просмотреть файл

@ -1494,7 +1494,7 @@ export default class MainController implements vscode.Disposable {
this.untitledSqlService,
planContents,
docName
)
);
executionPlanController.revealToForeground();
}

Просмотреть файл

@ -0,0 +1,132 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as l10n from '@vscode/l10n';
export class LocConstants {
private static _instance = new LocConstants();
private constructor() {
}
public static getInstance(): LocConstants {
return LocConstants._instance;
}
public static createInstance(): void {
LocConstants._instance = new LocConstants();
}
public get objectExplorerFiltering() {
return {
error: l10n.t('Error'),
clearAll: l10n.t('Clear All'),
close: l10n.t('Close'),
ok: l10n.t('OK'),
and: l10n.t('And'),
contains: l10n.t('Contains'),
notContains: l10n.t('Not Contains'),
startsWith: l10n.t('Starts With'),
notStartsWith: l10n.t('Not Starts With'),
endsWith: l10n.t('Ends With'),
notEndsWith: l10n.t('Not Ends With'),
equals: l10n.t('Equals'),
notEquals: l10n.t('Not Equals'),
lessThan: l10n.t('Less Than'),
lessThanOrEquals: l10n.t('Less Than Or Equals'),
greaterThan: l10n.t('Greater Than'),
greaterThanOrEquals: l10n.t('Greater Than Or Equals'),
between: l10n.t('Between'),
notBetween: l10n.t('Not Between'),
path: (path: string) => l10n.t({
message: 'Path: {0}',
args: [path],
comment: ['{0} is the path of the node in the object explorer']
}),
firstValueEmptyError: (operator: string, filterName: string) => l10n.t({
message: 'The first value must be set for the {0} operator in the {1} filter',
args: [operator, filterName],
comment: ['{0} is the operator for the filter', '{1} is the name of the filter']
}),
secondValueEmptyError: (operator: string, filterName: string) => l10n.t({
message: 'The second value must be set for the {0} operator in the {1} filter',
args: [operator, filterName],
comment: ['{0} is the operator for the filter', '{1} is the name of the filter']
}),
firstValueLessThanSecondError: (operator: string, filterName: string) => l10n.t({
message: 'The first value must be less than the second value for the {0} operator in the {1} filter',
args: [operator, filterName],
comment: ['{0} is the operator for the filter', '{1} is the name of the filter']
}),
property: l10n.t('Property'),
operator: l10n.t('Operator'),
value: l10n.t('Value'),
clear: l10n.t('Clear')
};
};
public get tableDesigner() {
return {
publishingChanges: l10n.t('Publishing Changes'),
changesPublishedSuccessfully: l10n.t('Changes published successfully'),
closeDesigner: l10n.t('Close Designer'),
continueEditing: l10n.t('Continue Editing'),
loadingTableDesigner: l10n.t('Loading Table Designer'),
errorLoadingPreview: l10n.t('Error loading preview'),
retry: l10n.t('Retry'),
updateDatabase: l10n.t('Update Database'),
generateScript: l10n.t('Generate Script'),
publish: l10n.t('Publish'),
previewDatabaseUpdates: l10n.t('Preview Database Updates'),
close: l10n.t('Close'),
}
};
public get connectionDialog() {
return {
connect: l10n.t('Connect'),
advancedConnectionSettings: l10n.t('Advanced Connection Settings'),
advancedSettings: l10n.t('Advanced'),
testConnection: l10n.t('Test Connection'),
connectToSQLServer: l10n.t('Connect to SQL Server'),
parameters: l10n.t('Parameters'),
connectionString: l10n.t('Connection String'),
browseAzure: l10n.t('Browse Azure'),
recentConnections: l10n.t('Recent Connections'),
};
}
public get executionPlan() {
return {
queryCostRelativeToScript: (index: number, costPercentage: string) => l10n.t({
message: 'Query {0}: Query cost (relative to the script): {1}%',
args: [index, costPercentage],
comment: ['{0} is the query number', '{1} is the query cost']
}),
equals: l10n.t('Equals'),
contains: l10n.t('Contains'),
actualElapsedTime: l10n.t('Actual Elapsed Time'),
actualElapsedCpuTime: l10n.t('Actual Elapsed CPU Time'),
cost: l10n.t('Cost'),
subtreeCost: l10n.t('Subtree Cost'),
actualNumberOfRowsForAllExecutions: l10n.t('Actual Number of Rows For All Executions'),
numberOfRowsRead: l10n.t('Number of Rows Read'),
off: l10n.t('Off'),
metric: l10n.t('Metric'),
findNodes: l10n.t('Find Nodes'),
savePlan: l10n.t('Save Plan'),
openXml: l10n.t('Open XML'),
openQuery: l10n.t('Open Query'),
zoomIn: l10n.t('Zoom In'),
zoomOut: l10n.t('Zoom Out'),
zoomToFit: l10n.t('Zoom to Fit'),
customZoom: l10n.t('Custom Zoom'),
findNode: l10n.t('Find Node'),
highlightExpensiveOperation: l10n.t('Highlight Expensive Operation'),
toggleTooltips: l10n.t('Toggle Tooltips')
}
}
}
export let locConstants = LocConstants.getInstance();

Просмотреть файл

@ -8,6 +8,7 @@ import { createContext, useContext, useEffect, useState } from "react";
import { WebviewApi } from "vscode-webview";
import { WebviewRpc } from "./rpc";
import * as l10n from '@vscode/l10n';
import { LocConstants } from "./locConstants";
/**
* Context for vscode webview functionality like theming, state management, rpc and vscode api.
@ -91,6 +92,9 @@ export function VscodeWebviewProvider<State, Reducers>({ children }: VscodeWebvi
await l10n.config({
contents: fileContents
});
//delay 100ms to make sure the l10n is initialized before the component is rendered
await new Promise(resolve => setTimeout(resolve, 1000));
LocConstants.createInstance();
}
/**
* This is a hack to force a re-render of the component when the localization filecontent

Просмотреть файл

@ -7,6 +7,7 @@ import { Button, Spinner } from "@fluentui/react-components";
import { CSSProperties, useContext } from "react";
import { ConnectionDialogContext } from "./connectionDialogStateProvider";
import { ApiStatus } from "../../../sharedInterfaces/webview";
import { locConstants } from "../../common/locConstants";
export const ConnectButton = ({style}: {style?: CSSProperties}) => {
const connectionDialogContext = useContext(ConnectionDialogContext);
@ -31,7 +32,7 @@ export const ConnectButton = ({style}: {style?: CSSProperties}) => {
}
iconPosition="after"
icon={ connectionDialogContext.state.connectionStatus === ApiStatus.Loading ? <Spinner size='tiny' /> : undefined}>
Connect
{locConstants.connectionDialog.connect}
</Button>
);
};

Просмотреть файл

@ -16,12 +16,12 @@ import {
OverlayDrawer,
} from "@fluentui/react-components";
import { Dismiss24Regular } from "@fluentui/react-icons";
import { ConnectionDialogContext } from "./connectionDialogStateProvider";
import { FormField } from "../../common/forms/form.component";
import { FormItemSpec } from "../../common/forms/form";
import { IConnectionDialogProfile } from "../../../sharedInterfaces/connectionDialog";
import { ConnectButton } from "./connectButton";
import { locConstants } from "../../common/locConstants";
export const ConnectionFormPage = () => {
const connectionDialogContext = useContext(ConnectionDialogContext);
@ -69,7 +69,7 @@ export const ConnectionFormPage = () => {
/>
}
>
Advanced Connection Settings
{locConstants.connectionDialog.advancedConnectionSettings}
</DrawerHeaderTitle>
</DrawerHeader>
@ -130,7 +130,7 @@ export const ConnectionFormPage = () => {
margin: "0px 10px",
}}
>
Advanced
{locConstants.connectionDialog.advancedSettings}
</Button>
<div style={{ display: "flex", marginLeft: "auto" }}>
<Button
@ -144,7 +144,7 @@ export const ConnectionFormPage = () => {
margin: "0px 10px",
}}
>
Test Connection
{locConstants.connectionDialog.testConnection}
</Button>
<ConnectButton />
</div>

Просмотреть файл

@ -6,13 +6,13 @@
import { useContext } from "react";
import { Text, Image, webLightTheme } from "@fluentui/react-components";
import { ConnectionDialogContext } from "./connectionDialogStateProvider";
import { locConstants } from "../../common/locConstants";
const sqlServerImage = require('../../../../media/sqlServer_light.svg');
const sqlServerImageDark = require('../../../../media/sqlServer_dark.svg');
export const ConnectionHeader = () => {
const connectionDialogContext = useContext(ConnectionDialogContext);
return (
<div style={
{
@ -31,7 +31,7 @@ export const ConnectionHeader = () => {
{
lineHeight: '60px'
}
} weight='medium'>Connect to SQL Server</Text>
} weight='medium'>{locConstants.connectionDialog.connectToSQLServer}</Text>
</div>
);
};

Просмотреть файл

@ -13,6 +13,7 @@ import { ConnectionFormPage } from "./connectionFormPage";
import { ConnectionStringPage } from "./connectionStringPage";
import { FormField, useFormStyles } from "../../common/forms/form.component";
import { FormItemSpec } from "../../common/forms/form";
import { locConstants } from "../../common/locConstants";
function renderContent(connectionDialogContext: ConnectionDialogContextProps): ReactNode {
switch (connectionDialogContext?.state.selectedInputMode) {
@ -55,9 +56,9 @@ export const ConnectionInfoFormContainer = () => {
onChange={(_, data) => { connectionDialogContext.setConnectionInputType(data.value as ConnectionInputMode); }}
value={connectionDialogContext.state.selectedInputMode}
>
<Radio value={ConnectionInputMode.Parameters} label="Parameters" />
<Radio value={ConnectionInputMode.ConnectionString} label="Connection String" />
<Radio value={ConnectionInputMode.AzureBrowse} label="Browse Azure" />
<Radio value={ConnectionInputMode.Parameters} label={locConstants.connectionDialog.parameters} />
<Radio value={ConnectionInputMode.ConnectionString} label={locConstants.connectionDialog.connectionString} />
<Radio value={ConnectionInputMode.AzureBrowse} label={locConstants.connectionDialog.browseAzure} />
</RadioGroup>
</Field>
</div>

Просмотреть файл

@ -16,6 +16,7 @@ export const ConnectionStringPage = () => {
if (connectionDialogContext === undefined) {
return undefined;
}
let index = 0;
return (
<div>

Просмотреть файл

@ -7,6 +7,7 @@ import { Text, Tree, TreeItem, TreeItemLayout, makeStyles, tokens } from "@fluen
import { ServerRegular } from "@fluentui/react-icons";
import { useContext } from "react";
import { ConnectionDialogContext } from "./connectionDialogStateProvider";
import { locConstants } from "../../common/locConstants";
const useStyles = makeStyles({
paneTitle: {
@ -45,7 +46,7 @@ export const MruConnectionsContainer = () => {
return (
<div>
<div className={styles.paneTitle}>
<Text weight="semibold" className={styles.paneTitle}>Recent Connections</Text>
<Text weight="semibold" className={styles.paneTitle}>{locConstants.connectionDialog.recentConnections}</Text>
</div>
<Tree >
{

Просмотреть файл

@ -16,7 +16,7 @@ import { Checkmark20Regular, Dismiss20Regular } from '@fluentui/react-icons';
import { IconStack } from './iconMenu';
import { FindNode } from './findNodes';
import { HighlightExpensiveOperations } from './highlightExpensiveOperations';
import * as l10n from '@vscode/l10n';
import { locConstants } from '../../common/locConstants';
const useStyles = makeStyles({
panelContainer: {
@ -64,7 +64,7 @@ interface ExecutionPlanGraphProps {
export const ExecutionPlanGraph: React.FC<ExecutionPlanGraphProps> = ({
graphIndex
}) => {
}) => {
const classes = useStyles();
const state = useContext(ExecutionPlanContext);
const executionPlanState = state?.state;
@ -150,37 +150,33 @@ export const ExecutionPlanGraph: React.FC<ExecutionPlanGraphProps> = ({
const getQueryCostPercentage = () => {
const percentage = (cost / executionPlanState!.totalCost!) * 100;
return percentage.toFixed(2) + '%';
return percentage.toFixed(2);
};
const queryCostHeader = l10n.t({
message: 'Query {0}: Query cost (relative to the script): {1}',
args: [graphIndex + 1, getQueryCostPercentage()],
comment: ['{0} is the query number', '{1} is the query cost']
});
return (
<div id="panelContainer" className={classes.panelContainer}>
<div id="planContainer" className={classes.planContainer}>
<div id="queryCostContainer" className={classes.queryCostContainer} style={{background:utils.background(executionPlanState!.theme!)}}>
{queryCostHeader}<br />{query}
<div id="queryCostContainer" className={classes.queryCostContainer} style={{ background: utils.background(executionPlanState!.theme!) }}>
{
locConstants.executionPlan.queryCostRelativeToScript(graphIndex + 1, getQueryCostPercentage())
}<br />{query}
</div>
<div id={`queryPlanParent${graphIndex + 1}`} className={classes.queryPlanParent}></div>
{customZoomClicked ? (
<div id="customZoomInputContainer" className={classes.inputContainer} style={{background:utils.iconBackground(executionPlanState!.theme!)}}>
<Input id="customZoomInputBox" type="number" min={1} defaultValue={Math.floor(zoomNumber).toString()} onChange={(e) => setZoomNumber(Number(e.target.value))} style={{ width: '100px', height: '25px', fontSize: '12px' }}/>
<div id="customZoomInputContainer" className={classes.inputContainer} style={{ background: utils.iconBackground(executionPlanState!.theme!) }}>
<Input id="customZoomInputBox" type="number" min={1} defaultValue={Math.floor(zoomNumber).toString()} onChange={(e) => setZoomNumber(Number(e.target.value))} style={{ width: '100px', height: '25px', fontSize: '12px' }} />
<Button onClick={handleCustomZoomInput} icon={<Checkmark20Regular />} />
<Button icon={<Dismiss20Regular />} onClick={() => setCustomZoomClicked(false)}/>
<Button icon={<Dismiss20Regular />} onClick={() => setCustomZoomClicked(false)} />
</div>
) : null}
{findNodeClicked ? (
<FindNode executionPlanView={executionPlanView} setExecutionPlanView={setExecutionPlanView} findNodeOptions={findNodeOptions} setFindNodeClicked={setFindNodeClicked}/>
<FindNode executionPlanView={executionPlanView} setExecutionPlanView={setExecutionPlanView} findNodeOptions={findNodeOptions} setFindNodeClicked={setFindNodeClicked} />
) : null}
{highlightOpsClicked ? (
<HighlightExpensiveOperations executionPlanView={executionPlanView} setExecutionPlanView={setExecutionPlanView} setHighlightOpsClicked={setHighlightOpsClicked}/>
<HighlightExpensiveOperations executionPlanView={executionPlanView} setExecutionPlanView={setExecutionPlanView} setHighlightOpsClicked={setHighlightOpsClicked} />
) : null}
</div>
<IconStack executionPlanView={executionPlanView} setExecutionPlanView={setExecutionPlanView} setZoomNumber={setZoomNumber} setCustomZoomClicked={setCustomZoomClicked} setFindNodeClicked={setFindNodeClicked} setHighlightOpsClicked={setHighlightOpsClicked} query={query}/>
<IconStack executionPlanView={executionPlanView} setExecutionPlanView={setExecutionPlanView} setZoomNumber={setZoomNumber} setCustomZoomClicked={setCustomZoomClicked} setFindNodeClicked={setFindNodeClicked} setHighlightOpsClicked={setHighlightOpsClicked} query={query} />
</div>
);
};

Просмотреть файл

@ -12,7 +12,6 @@ export interface ExecutionPlanWebviewState {
theme?: string;
totalCost?: number;
loadState?: ApiStatus;
localizedConstants?: any;
errorMessage?: string;
}

Просмотреть файл

@ -10,6 +10,7 @@ import './executionPlan.css';
import { Button, Combobox, Dropdown, Input, Option, makeStyles } from '@fluentui/react-components';
import { ArrowUp20Regular, ArrowDown20Regular, Dismiss20Regular } from '@fluentui/react-icons';
import * as ep from './executionPlanInterfaces';
import { locConstants } from '../../common/locConstants';
const useStyles = makeStyles({
inputContainer: {
@ -44,20 +45,27 @@ interface FindNodeProps {
setFindNodeClicked: any;
}
export const FindNode : React.FC<FindNodeProps> = ({
export const FindNode: React.FC<FindNodeProps> = ({
executionPlanView,
setExecutionPlanView,
findNodeOptions,
setFindNodeClicked
}) => {
}) => {
const classes = useStyles();
const state = useContext(ExecutionPlanContext);
const executionPlanState = state?.state;
const LocalizedConstants = executionPlanState!.localizedConstants!;
const findNodeComparisonOptions: string[] = [LocalizedConstants.equals, LocalizedConstants.contains,">","<",">=","<=","<>"];
const findNodeComparisonOptions: string[] = [
locConstants.executionPlan.equals,
locConstants.executionPlan.contains,
">",
"<",
">=",
"<=",
"<>"
];
const findNodeEnum: ep.SearchType[] = [ep.SearchType.Equals, ep.SearchType.Contains, ep.SearchType.GreaterThan, ep.SearchType.LesserThan,
ep.SearchType.GreaterThanEqualTo, ep.SearchType.LesserThanEqualTo, ep.SearchType.LesserAndGreaterThan];
ep.SearchType.GreaterThanEqualTo, ep.SearchType.LesserThanEqualTo, ep.SearchType.LesserAndGreaterThan];
const [findNodeSelection, setFindNodeSelection] = useState(findNodeOptions[0]);
const [findNodeComparisonSelection, setFindNodeComparisonSelection] = useState(findNodeComparisonOptions[0]);
@ -101,28 +109,28 @@ export const FindNode : React.FC<FindNodeProps> = ({
};
return (
<div id="findNodeInputContainer" className={classes.inputContainer} style={{background:utils.iconBackground(executionPlanState!.theme!)}}>
<div>{LocalizedConstants.findNodes}</div>
<Combobox id="findNodeDropdown" className={classes.combobox} defaultValue={findNodeOptions[0]} onOptionSelect={(_, data) => {setFindNodeSelection(data.optionText ?? findNodeOptions[0]); setFindNodeResultsIndex(-1); setFindNodeResults([])}}>
<div style={{maxHeight:"250px", maxWidth:"100px"}}>
{findNodeOptions.map((option) => (
<Option key={option}>
{option}
</Option>
))}
<div id="findNodeInputContainer" className={classes.inputContainer} style={{ background: utils.iconBackground(executionPlanState!.theme!) }}>
<div>{locConstants.executionPlan.findNodes}</div>
<Combobox id="findNodeDropdown" className={classes.combobox} defaultValue={findNodeOptions[0]} onOptionSelect={(_, data) => { setFindNodeSelection(data.optionText ?? findNodeOptions[0]); setFindNodeResultsIndex(-1); setFindNodeResults([]) }}>
<div style={{ maxHeight: "250px", maxWidth: "100px" }}>
{findNodeOptions.map((option) => (
<Option key={option}>
{option}
</Option>
))}
</div>
</Combobox>
<Dropdown id="findNodeComparisonDropdown" className={classes.dropdown} defaultValue={findNodeComparisonOptions[0]} onOptionSelect={(_, data) => {setFindNodeComparisonSelection(data.optionText ?? findNodeComparisonOptions[0]); setFindNodeResultsIndex(-1); setFindNodeResults([])}}>
<Dropdown id="findNodeComparisonDropdown" className={classes.dropdown} defaultValue={findNodeComparisonOptions[0]} onOptionSelect={(_, data) => { setFindNodeComparisonSelection(data.optionText ?? findNodeComparisonOptions[0]); setFindNodeResultsIndex(-1); setFindNodeResults([]) }}>
{findNodeComparisonOptions.map((option) => (
<Option key={option}>
{option}
</Option>
))}
</Dropdown>
<Input id="findNodeInputBox" type="text" className={classes.combobox} onChange={(e) => {setFindNodeSearchValue(e.target.value); setFindNodeResultsIndex(-1); setFindNodeResults([])}}/>
<Input id="findNodeInputBox" type="text" className={classes.combobox} onChange={(e) => { setFindNodeSearchValue(e.target.value); setFindNodeResultsIndex(-1); setFindNodeResults([]) }} />
<Button onClick={() => handleFoundNode(-1)} icon={<ArrowUp20Regular />} />
<Button onClick={() => handleFoundNode(1)} icon={<ArrowDown20Regular />} />
<Button icon={<Dismiss20Regular />} onClick={() => setFindNodeClicked(false)}/>
<Button icon={<Dismiss20Regular />} onClick={() => setFindNodeClicked(false)} />
</div>
);
};

Просмотреть файл

@ -10,6 +10,7 @@ import './executionPlan.css';
import { Button, Combobox, makeStyles, Option } from '@fluentui/react-components';
import { Checkmark20Regular, Dismiss20Regular } from '@fluentui/react-icons';
import * as ep from './executionPlanInterfaces';
import { locConstants } from '../../common/locConstants';
const useStyles = makeStyles({
inputContainer: {
@ -44,12 +45,18 @@ export const HighlightExpensiveOperations: React.FC<HighlightExpensiveOperations
const classes = useStyles();
const state = useContext(ExecutionPlanContext);
const executionPlanState = state?.state;
const LocalizedConstants = executionPlanState!.localizedConstants!;
const [highlightMetricSelected, setHighlightMetricSelected] = useState('');
const highlightMetricOptions: string[] =
[LocalizedConstants.actualElapsedTime, LocalizedConstants.actualElapsedCpuTime, LocalizedConstants.cost, LocalizedConstants.subtreeCost,
LocalizedConstants.actualNumberOfRows, LocalizedConstants.numRowsRead, LocalizedConstants.off];
[
locConstants.executionPlan.actualElapsedTime,
locConstants.executionPlan.actualElapsedCpuTime,
locConstants.executionPlan.cost,
locConstants.executionPlan.subtreeCost,
locConstants.executionPlan.actualNumberOfRowsForAllExecutions,
locConstants.executionPlan.numberOfRowsRead,
locConstants.executionPlan.off
];
const highlightMetricOptionsEnum: ep.ExpensiveMetricType[] =
[ep.ExpensiveMetricType.ActualElapsedTime, ep.ExpensiveMetricType.ActualElapsedCpuTime, ep.ExpensiveMetricType.Cost, ep.ExpensiveMetricType.SubtreeCost, ep.ExpensiveMetricType.ActualNumberOfRowsForAllExecutions, ep.ExpensiveMetricType.NumberOfRowsRead, ep.ExpensiveMetricType.Off];
@ -77,7 +84,7 @@ export const HighlightExpensiveOperations: React.FC<HighlightExpensiveOperations
return (
<div id="highlightExpensiveOpsContainer" className={classes.inputContainer} style={{background:utils.iconBackground(executionPlanState!.theme!)}}>
<div>{LocalizedConstants.metric}</div>
<div>{locConstants.executionPlan.metric}</div>
<Combobox id="highlightExpensiveOpsDropdown" onOptionSelect={(_, data) => setHighlightMetricSelected(data.optionText ?? '')}>
<div style={{maxHeight:"250px"}}>
{highlightMetricOptions.map((option) => (

Просмотреть файл

@ -8,6 +8,7 @@ import { ExecutionPlanContext } from "./executionPlanStateProvider";
import * as utils from './queryPlanSetup';
import './executionPlan.css';
import { makeStyles } from '@fluentui/react-components';
import { locConstants } from '../../common/locConstants';
const useStyles = makeStyles({
iconStack: {
@ -60,7 +61,6 @@ export const IconStack : React.FC<IconStackProps> = ({
const classes = useStyles();
const state = useContext(ExecutionPlanContext);
const executionPlanState = state?.state;
const LocalizedConstants = executionPlanState!.localizedConstants!;
const [tooltipsEnabled, setTooltipsEnabled] = useState(true);
enum InputEnum {
CustomZoom,
@ -68,6 +68,17 @@ export const IconStack : React.FC<IconStackProps> = ({
HighlightOps
}
const SAVE_PLAN = locConstants.executionPlan.savePlan;
const OPEN_XML = locConstants.executionPlan.openXml;
const OPEN_QUERY = locConstants.executionPlan.openQuery;
const ZOOM_IN = locConstants.executionPlan.zoomIn;
const ZOOM_OUT = locConstants.executionPlan.zoomOut;
const ZOOM_TO_FIT = locConstants.executionPlan.zoomToFit;
const CUSTOM_ZOOM = locConstants.executionPlan.customZoom;
const FIND_NODE = locConstants.executionPlan.findNode;
const HIGHLIGHT_OPS = locConstants.executionPlan.highlightExpensiveOperation;
const TOGGLE_TOOLTIPS = locConstants.executionPlan.toggleTooltips;
const handleSavePlan = async () => {
await state!.provider.saveExecutionPlan(executionPlanState!.sqlPlanContent!);
};
@ -132,40 +143,40 @@ export const IconStack : React.FC<IconStackProps> = ({
return (
<div id="iconStack" className={classes.iconStack} style={{outline: `2px solid ${utils.seperator(executionPlanState!.theme!)}`, background:`${utils.background(executionPlanState!.theme!)}`}}>
<div id="saveButton" className={classes.button} onClick={handleSavePlan} tabIndex={0} title={LocalizedConstants.savePlan} aria-label={LocalizedConstants.savePlan}>
<img className={classes.buttonImg} src={utils.save(executionPlanState!.theme!)} alt={LocalizedConstants.savePlan} width="20" height="20" />
<div id="saveButton" className={classes.button} onClick={handleSavePlan} tabIndex={0} title={SAVE_PLAN} aria-label={SAVE_PLAN}>
<img className={classes.buttonImg} src={utils.save(executionPlanState!.theme!)} alt={SAVE_PLAN} width="20" height="20" />
</div>
<div id="showXmlButton" className={classes.button} onClick={handleShowXml} tabIndex={0} title={LocalizedConstants.openXml} aria-label={LocalizedConstants.openXml}>
<img className={classes.buttonImg} src={utils.openPlanFile(executionPlanState!.theme!)} alt={LocalizedConstants.openXml} width="20" height="20" />
<div id="showXmlButton" className={classes.button} onClick={handleShowXml} tabIndex={0} title={OPEN_XML} aria-label={OPEN_XML}>
<img className={classes.buttonImg} src={utils.openPlanFile(executionPlanState!.theme!)} alt={OPEN_XML} width="20" height="20" />
</div>
<div id="showQueryButton" className={classes.button} onClick={handleShowQuery} tabIndex={0} title={LocalizedConstants.openQuery} aria-label={LocalizedConstants.openQuery}>
<img className={classes.buttonImg} src={utils.openQuery(executionPlanState!.theme!)} alt={LocalizedConstants.openQuery}width="20" height="20" />
<div id="showQueryButton" className={classes.button} onClick={handleShowQuery} tabIndex={0} title={OPEN_QUERY} aria-label={OPEN_QUERY}>
<img className={classes.buttonImg} src={utils.openQuery(executionPlanState!.theme!)} alt={OPEN_QUERY}width="20" height="20" />
</div>
<hr className={classes.seperator} style={{background:utils.seperator(executionPlanState!.theme!)}}></hr>
<div id="zoomInButton" className={classes.button} onClick={handleZoomIn} tabIndex={0} title={LocalizedConstants.zoomIn} aria-label={LocalizedConstants.zoomIn}>
<img className={classes.buttonImg} src={utils.zoomIn(executionPlanState!.theme!)} alt={LocalizedConstants.zoomIn} width="20" height="20" />
<div id="zoomInButton" className={classes.button} onClick={handleZoomIn} tabIndex={0} title={ZOOM_IN} aria-label={ZOOM_IN}>
<img className={classes.buttonImg} src={utils.zoomIn(executionPlanState!.theme!)} alt={ZOOM_IN} width="20" height="20" />
</div>
<div id="zoomOutButton" className={classes.button} onClick={handleZoomOut} tabIndex={0} title={LocalizedConstants.zoomOut} aria-label={LocalizedConstants.zoomOut}>
<img className={classes.buttonImg} src={utils.zoomOut(executionPlanState!.theme!)} alt={LocalizedConstants.zoomOut} width="20" height="20" />
<div id="zoomOutButton" className={classes.button} onClick={handleZoomOut} tabIndex={0} title={ZOOM_OUT} aria-label={ZOOM_OUT}>
<img className={classes.buttonImg} src={utils.zoomOut(executionPlanState!.theme!)} alt={ZOOM_OUT} width="20" height="20" />
</div>
<div id="zoomToFitButton" className={classes.button} onClick={handleZoomToFit} tabIndex={0} title={LocalizedConstants.zoomToFit} aria-label={LocalizedConstants.zoomToFit}>
<img className={classes.buttonImg} src={utils.zoomToFit(executionPlanState!.theme!)} alt={LocalizedConstants.zoomToFit} width="20" height="20" />
<div id="zoomToFitButton" className={classes.button} onClick={handleZoomToFit} tabIndex={0} title={ZOOM_TO_FIT} aria-label={ZOOM_TO_FIT}>
<img className={classes.buttonImg} src={utils.zoomToFit(executionPlanState!.theme!)} alt={ZOOM_TO_FIT} width="20" height="20" />
</div>
<div id="customZoomButton" className={classes.button} onClick={() => setInputContainer(InputEnum.CustomZoom)} tabIndex={0} title={LocalizedConstants.customZoom} aria-label={LocalizedConstants.customZoom}>
<img className={classes.buttonImg} src={utils.customZoom(executionPlanState!.theme!)} alt={LocalizedConstants.customZoom} width="20" height="20" />
<div id="customZoomButton" className={classes.button} onClick={() => setInputContainer(InputEnum.CustomZoom)} tabIndex={0} title={CUSTOM_ZOOM} aria-label={CUSTOM_ZOOM}>
<img className={classes.buttonImg} src={utils.customZoom(executionPlanState!.theme!)} alt={CUSTOM_ZOOM} width="20" height="20" />
</div>
<hr className={classes.seperator} style={{background:utils.seperator(executionPlanState!.theme!)}}></hr>
<div id="findNodeButton" className={classes.button} onClick={() => setInputContainer(InputEnum.FindNode)} tabIndex={0} title={LocalizedConstants.findNode} aria-label={LocalizedConstants.findNode}>
<img className={classes.buttonImg} src={utils.search(executionPlanState!.theme!)} alt={LocalizedConstants.findNode} width="20" height="20" />
<div id="findNodeButton" className={classes.button} onClick={() => setInputContainer(InputEnum.FindNode)} tabIndex={0} title={FIND_NODE} aria-label={FIND_NODE}>
<img className={classes.buttonImg} src={utils.search(executionPlanState!.theme!)} alt={FIND_NODE} width="20" height="20" />
</div>
<div id="highlightOpsButton" className={classes.button} onClick={() => setInputContainer(InputEnum.HighlightOps)} tabIndex={0} title={LocalizedConstants.highlightOps} aria-label={LocalizedConstants.highlightOps}>
<img className={classes.buttonImg} src={utils.highlightOps(executionPlanState!.theme!)} alt={LocalizedConstants.highlightOps} width="20" height="20" />
<div id="highlightOpsButton" className={classes.button} onClick={() => setInputContainer(InputEnum.HighlightOps)} tabIndex={0} title={HIGHLIGHT_OPS} aria-label={HIGHLIGHT_OPS}>
<img className={classes.buttonImg} src={utils.highlightOps(executionPlanState!.theme!)} alt={HIGHLIGHT_OPS} width="20" height="20" />
</div>
<div id="tooltipsButton" className={classes.button} onClick={handleToggleTooltips} tabIndex={0} title={LocalizedConstants.toggleTooltips} aria-label={LocalizedConstants.toggleTooltips}>
<div id="tooltipsButton" className={classes.button} onClick={handleToggleTooltips} tabIndex={0} title={TOGGLE_TOOLTIPS} aria-label={TOGGLE_TOOLTIPS}>
{tooltipsEnabled ? (
<img className={classes.buttonImg} src={utils.enableTooltip(executionPlanState!.theme!)} alt={LocalizedConstants.toggleTooltips} width="20" height="20" />
<img className={classes.buttonImg} src={utils.enableTooltip(executionPlanState!.theme!)} alt={TOGGLE_TOOLTIPS} width="20" height="20" />
):
<img className={classes.buttonImg} src={utils.disableTooltip(executionPlanState!.theme!)} alt={LocalizedConstants.toggleTooltips} width="20" height="20" />
<img className={classes.buttonImg} src={utils.disableTooltip(executionPlanState!.theme!)} alt={TOGGLE_TOOLTIPS} width="20" height="20" />
}
</div>
</div>

Просмотреть файл

@ -9,6 +9,8 @@ import { ObjectExplorerFilterContext } from "./ObjectExplorerFilterStateProvider
import * as vscodeMssql from 'vscode-mssql';
import { EraserRegular } from "@fluentui/react-icons";
import { NodeFilterOperator, NodeFilterPropertyDataType, ObjectExplorerPageFilter } from "../../../sharedInterfaces/objectExplorerFilter";
import * as l10n from "@vscode/l10n";
import { locConstants } from "../../common/locConstants";
export const useStyles = makeStyles({
root: {
@ -50,6 +52,137 @@ export const ObjectExplorerFilterPage = () => {
const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined);
const [uiFilters, setUiFilters] = useState<ObjectExplorerPageFilter[]>([]);
const AND = locConstants.objectExplorerFiltering.and;
const CONTAINS = locConstants.objectExplorerFiltering.contains;
const NOT_CONTAINS = locConstants.objectExplorerFiltering.notContains;
const STARTS_WITH = locConstants.objectExplorerFiltering.startsWith;
const NOT_STARTS_WITH = locConstants.objectExplorerFiltering.notStartsWith;
const ENDS_WITH = locConstants.objectExplorerFiltering.endsWith;
const NOT_ENDS_WITH = locConstants.objectExplorerFiltering.notEndsWith;
const EQUALS = locConstants.objectExplorerFiltering.equals;
const NOT_EQUALS = locConstants.objectExplorerFiltering.notEquals;
const LESS_THAN = locConstants.objectExplorerFiltering.lessThan;
const LESS_THAN_OR_EQUALS = locConstants.objectExplorerFiltering.lessThanOrEquals;
const GREATER_THAN = locConstants.objectExplorerFiltering.greaterThan;
const GREATER_THAN_OR_EQUALS = locConstants.objectExplorerFiltering.greaterThanOrEquals;
const BETWEEN = locConstants.objectExplorerFiltering.between;
const NOT_BETWEEN = locConstants.objectExplorerFiltering.notBetween;
function getFilterOperatorString(operator: NodeFilterOperator | undefined): string | undefined {
if (operator === undefined) {
return undefined;
}
switch (operator) {
case NodeFilterOperator.Contains:
return CONTAINS;
case NodeFilterOperator.NotContains:
return NOT_CONTAINS;
case NodeFilterOperator.StartsWith:
return STARTS_WITH;
case NodeFilterOperator.NotStartsWith:
return NOT_STARTS_WITH;
case NodeFilterOperator.EndsWith:
return ENDS_WITH;
case NodeFilterOperator.NotEndsWith:
return NOT_ENDS_WITH;
case NodeFilterOperator.Equals:
return EQUALS;
case NodeFilterOperator.NotEquals:
return NOT_EQUALS;
case NodeFilterOperator.LessThan:
return LESS_THAN;
case NodeFilterOperator.LessThanOrEquals:
return LESS_THAN_OR_EQUALS;
case NodeFilterOperator.GreaterThan:
return GREATER_THAN;
case NodeFilterOperator.GreaterThanOrEquals:
return GREATER_THAN_OR_EQUALS;
case NodeFilterOperator.Between:
return BETWEEN;
case NodeFilterOperator.NotBetween:
return NOT_BETWEEN;
default:
return '';
}
}
function getFilterOperatorEnum(operator: string): NodeFilterOperator {
switch (operator) {
case CONTAINS:
return NodeFilterOperator.Contains;
case NOT_CONTAINS:
return NodeFilterOperator.NotContains;
case STARTS_WITH:
return NodeFilterOperator.StartsWith;
case NOT_STARTS_WITH:
return NodeFilterOperator.NotStartsWith;
case ENDS_WITH:
return NodeFilterOperator.EndsWith;
case NOT_ENDS_WITH:
return NodeFilterOperator.NotEndsWith;
case EQUALS:
return NodeFilterOperator.Equals;
case NOT_EQUALS:
return NodeFilterOperator.NotEquals;
case LESS_THAN:
return NodeFilterOperator.LessThan;
case LESS_THAN_OR_EQUALS:
return NodeFilterOperator.LessThanOrEquals;
case GREATER_THAN:
return NodeFilterOperator.GreaterThan;
case GREATER_THAN_OR_EQUALS:
return NodeFilterOperator.GreaterThanOrEquals;
case BETWEEN:
return NodeFilterOperator.Between;
case NOT_BETWEEN:
return NodeFilterOperator.NotBetween;
default:
return NodeFilterOperator.Equals;
}
}
function getFilterOperators(property: vscodeMssql.NodeFilterProperty): string[] {
switch (property.type) {
case NodeFilterPropertyDataType.Boolean:
return [EQUALS, NOT_EQUALS];
case NodeFilterPropertyDataType.String:
return [CONTAINS, NOT_CONTAINS, STARTS_WITH, NOT_STARTS_WITH, ENDS_WITH, NOT_ENDS_WITH, EQUALS, NOT_EQUALS];
case NodeFilterPropertyDataType.Number:
return [EQUALS, NOT_EQUALS, LESS_THAN, LESS_THAN_OR_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUALS, BETWEEN, NOT_BETWEEN];
case NodeFilterPropertyDataType.Date:
return [EQUALS, NOT_EQUALS, LESS_THAN, LESS_THAN_OR_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUALS, BETWEEN, NOT_BETWEEN];
case NodeFilterPropertyDataType.Choice:
return [EQUALS, NOT_EQUALS];
default:
return [];
}
}
function getFilterChoices(property: vscodeMssql.NodeFilterChoiceProperty | vscodeMssql.NodeFilterProperty): {
name: string;
displayName: string;
}[] | undefined {
switch (property.type) {
case NodeFilterPropertyDataType.Choice:
return (property as vscodeMssql.NodeFilterChoiceProperty).choices.map((choice) => {
return {
name: choice.value,
displayName: choice.displayName!
};
});
case NodeFilterPropertyDataType.Boolean:
return [{
name: 'true',
displayName: 'True'
}, {
name: 'false',
displayName: 'False'
}];
default:
return undefined;
}
}
useEffect(() => {
function setIntialFocus() {
const input = document.getElementById('input-0');
@ -80,6 +213,7 @@ export const ObjectExplorerFilterPage = () => {
setErrorMessage(undefined);
}, [provider?.state?.filterProperties]);
function renderCell(columnId: TableColumnId, item: ObjectExplorerPageFilter) {
switch (columnId) {
case 'property':
@ -122,7 +256,7 @@ export const ObjectExplorerFilterPage = () => {
</Dropdown>
{
item.selectedOperator === BETWEEN || item.selectedOperator === NOT_BETWEEN &&
<Text className={classes.andOrText} size={200}>And</Text>
<Text className={classes.andOrText} size={200}>{AND}</Text>
}
</div>;
case 'value':
@ -220,25 +354,33 @@ export const ObjectExplorerFilterPage = () => {
createTableColumn(
{
columnId: 'property',
renderHeaderCell: () => <>Property</>,
renderHeaderCell: () => {
return <>{locConstants.objectExplorerFiltering.property}</>;
}
}
),
createTableColumn(
{
columnId: 'operator',
renderHeaderCell: () => <>Operator</>,
renderHeaderCell: () => {
return <>{locConstants.objectExplorerFiltering.operator}</>;
},
}
),
createTableColumn(
{
columnId: 'value',
renderHeaderCell: () => <>Value</>,
renderHeaderCell: () => {
return <>{locConstants.objectExplorerFiltering.value}</>;
},
}
),
createTableColumn(
{
columnId: 'clear',
renderHeaderCell: () => <>Clear</>,
renderHeaderCell: () => {
return <>{locConstants.objectExplorerFiltering.clear}</>;
}
}
)
];
@ -282,13 +424,13 @@ export const ObjectExplorerFilterPage = () => {
}
return (
<div className={classes.root}>
<Text size={400}>Filter Settings</Text>
<Body1Strong>Path: {provider?.state?.nodePath}</Body1Strong>
<Text size={400}>{l10n.t('Filter Settings')}</Text>
<Body1Strong>{locConstants.objectExplorerFiltering.path(provider?.state?.nodePath!)}</Body1Strong>
{
(errorMessage && errorMessage !== '') &&
<MessageBar intent={'error'}>
<MessageBarBody>
<MessageBarTitle>Error</MessageBarTitle>
<MessageBarTitle>{locConstants.objectExplorerFiltering.error}</MessageBarTitle>
{errorMessage}
</MessageBarBody>
</MessageBar>
@ -348,10 +490,10 @@ export const ObjectExplorerFilterPage = () => {
}
}
setUiFilters([...uiFilters]);
}}>Clear All</Button>
}}>{locConstants.objectExplorerFiltering.clearAll}</Button>
<Button appearance="secondary" onClick={() => {
provider.cancel();
}}>Close</Button>
}}>{locConstants.objectExplorerFiltering.close}</Button>
<Button appearance="primary" onClick={() => {
const filters: vscodeMssql.NodeFilter[] = uiFilters.map(f => {
@ -401,14 +543,11 @@ export const ObjectExplorerFilterPage = () => {
let value1 = (filter.value as string[] | number[])[0];
let value2 = (filter.value as string[] | number[])[1];
if (!value1 && value2) {
console.log(`The first value must be set for the ${getFilterOperatorString(filter.operator)} operator in the ${filter.name} filter`);
errorText = `The first value must be set for the ${getFilterOperatorString(filter.operator)} operator in the ${filter.name} filter`;
errorText = locConstants.objectExplorerFiltering.firstValueEmptyError(getFilterOperatorString(filter.operator)!, filter.name);
} else if (!value2 && value1) {
console.log(`The second value must be set for the ${getFilterOperatorString(filter.operator)} operator in the ${filter.name} filter`);
errorText = `The second value must be set for the ${getFilterOperatorString(filter.operator)} operator in the ${filter.name} filter`;
errorText = locConstants.objectExplorerFiltering.secondValueEmptyError(getFilterOperatorString(filter.operator)!, filter.name);
} else if (value1 > value2) {
console.log(`The first value must be less than the second value for the ${getFilterOperatorString(filter.operator)} operator in the ${filter.name} filter`);
errorText = `The first value must be less than the second value for the ${getFilterOperatorString(filter.operator)} operator in the ${filter.name} filter`;
errorText = locConstants.objectExplorerFiltering.firstValueLessThanSecondError(getFilterOperatorString(filter.operator)!, filter.name);
}
}
}
@ -417,139 +556,8 @@ export const ObjectExplorerFilterPage = () => {
return;
}
provider.submit(filters);
}}>OK</Button>
}}>{locConstants.objectExplorerFiltering.ok}</Button>
</div>
</div >
);
};
export function getFilterOperatorString(operator: NodeFilterOperator | undefined): string | undefined {
if (operator === undefined) {
return undefined;
}
switch (operator) {
case NodeFilterOperator.Contains:
return CONTAINS;
case NodeFilterOperator.NotContains:
return NOT_CONTAINS;
case NodeFilterOperator.StartsWith:
return STARTS_WITH;
case NodeFilterOperator.NotStartsWith:
return NOT_STARTS_WITH;
case NodeFilterOperator.EndsWith:
return ENDS_WITH;
case NodeFilterOperator.NotEndsWith:
return NOT_ENDS_WITH;
case NodeFilterOperator.Equals:
return EQUALS;
case NodeFilterOperator.NotEquals:
return NOT_EQUALS;
case NodeFilterOperator.LessThan:
return LESS_THAN;
case NodeFilterOperator.LessThanOrEquals:
return LESS_THAN_OR_EQUALS;
case NodeFilterOperator.GreaterThan:
return GREATER_THAN;
case NodeFilterOperator.GreaterThanOrEquals:
return GREATER_THAN_OR_EQUALS;
case NodeFilterOperator.Between:
return BETWEEN;
case NodeFilterOperator.NotBetween:
return NOT_BETWEEN;
default:
return '';
}
}
export function getFilterOperatorEnum(operator: string): NodeFilterOperator {
switch (operator) {
case CONTAINS:
return NodeFilterOperator.Contains;
case NOT_CONTAINS:
return NodeFilterOperator.NotContains;
case STARTS_WITH:
return NodeFilterOperator.StartsWith;
case NOT_STARTS_WITH:
return NodeFilterOperator.NotStartsWith;
case ENDS_WITH:
return NodeFilterOperator.EndsWith;
case NOT_ENDS_WITH:
return NodeFilterOperator.NotEndsWith;
case EQUALS:
return NodeFilterOperator.Equals;
case NOT_EQUALS:
return NodeFilterOperator.NotEquals;
case LESS_THAN:
return NodeFilterOperator.LessThan;
case LESS_THAN_OR_EQUALS:
return NodeFilterOperator.LessThanOrEquals;
case GREATER_THAN:
return NodeFilterOperator.GreaterThan;
case GREATER_THAN_OR_EQUALS:
return NodeFilterOperator.GreaterThanOrEquals;
case BETWEEN:
return NodeFilterOperator.Between;
case NOT_BETWEEN:
return NodeFilterOperator.NotBetween;
default:
return NodeFilterOperator.Equals;
}
}
const CONTAINS = 'Contains';
const NOT_CONTAINS = 'Not Contains';
const STARTS_WITH = 'Starts With';
const NOT_STARTS_WITH = 'Not Starts With';
const ENDS_WITH = 'Ends With';
const NOT_ENDS_WITH = 'Not Ends With';
const EQUALS = 'Equals';
const NOT_EQUALS = 'Not Equals';
const LESS_THAN = 'Less Than';
const LESS_THAN_OR_EQUALS = 'Less Than Or Equals';
const GREATER_THAN = 'Greater Than';
const GREATER_THAN_OR_EQUALS = 'Greater Than Or Equals';
const BETWEEN = 'Between';
const NOT_BETWEEN = 'Not Between';
export function getFilterChoices(property: vscodeMssql.NodeFilterChoiceProperty | vscodeMssql.NodeFilterProperty): {
name: string;
displayName: string;
}[] | undefined {
switch (property.type) {
case NodeFilterPropertyDataType.Choice:
return (property as vscodeMssql.NodeFilterChoiceProperty).choices.map((choice) => {
return {
name: choice.value,
displayName: choice.displayName!
};
});
case NodeFilterPropertyDataType.Boolean:
return [{
name: 'true',
displayName: 'True'
}, {
name: 'false',
displayName: 'False'
}];
default:
return undefined;
}
}
export function getFilterOperators(property: vscodeMssql.NodeFilterProperty): string[] {
switch (property.type) {
case NodeFilterPropertyDataType.Boolean:
return [EQUALS, NOT_EQUALS];
case NodeFilterPropertyDataType.String:
return [CONTAINS, NOT_CONTAINS, STARTS_WITH, NOT_STARTS_WITH, ENDS_WITH, NOT_ENDS_WITH, EQUALS, NOT_EQUALS];
case NodeFilterPropertyDataType.Number:
return [EQUALS, NOT_EQUALS, LESS_THAN, LESS_THAN_OR_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUALS, BETWEEN, NOT_BETWEEN];
case NodeFilterPropertyDataType.Date:
return [EQUALS, NOT_EQUALS, LESS_THAN, LESS_THAN_OR_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUALS, BETWEEN, NOT_BETWEEN];
case NodeFilterPropertyDataType.Choice:
return [EQUALS, NOT_EQUALS];
default:
return [];
}
}

Просмотреть файл

@ -19,6 +19,7 @@ const ObjectExplorerFilterStateProvider: React.FC<ObjectExplorerFilterStateProvi
return <ObjectExplorerFilterContext.Provider value={
{
isLocalizationLoaded: webviewState?.localization,
state: objectExplorerFilterState,
theme: webviewState?.theme,
submit: function (filters): void {

Просмотреть файл

@ -7,16 +7,17 @@ import { Dialog, DialogActions, DialogBody, DialogContent, DialogSurface, Dialog
import { ToolbarButton } from "@fluentui/react-toolbar";
import { DatabaseArrowDownRegular, ErrorCircleRegular } from "@fluentui/react-icons";
import { Button } from "@fluentui/react-button";
import { Spinner, makeStyles, shorthands } from "@fluentui/react-components";
import { Spinner, makeStyles } from "@fluentui/react-components";
import ReactMarkdown from 'react-markdown'
import { useContext } from "react";
import { TableDesignerContext } from "./tableDesignerStateProvider";
import { LoadState } from "../../../sharedInterfaces/tableDesigner";
import { locConstants } from "../../common/locConstants";
const useStyles = makeStyles({
dialogContent: {
height: '300px',
...shorthands.overflow('auto'),
overflow: 'auto',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
@ -50,9 +51,9 @@ export const DesignerChangesPreviewButton = () => {
const generateScriptIcon = () => {
switch (metadata?.apiState?.generateScriptState) {
case LoadState.Loading:
return <Spinner size='extra-small' />
return <Spinner size='extra-small' />;
case LoadState.Error:
return <ErrorCircleRegular />
return <ErrorCircleRegular />;
default:
return undefined;
}
@ -60,97 +61,109 @@ export const DesignerChangesPreviewButton = () => {
const getDialogContent = () => {
if (metadata?.apiState?.publishState === LoadState.Loading) {
return <>
<DialogContent className={classes.dialogContent}>
<Spinner label="Publishing Changes" labelPosition='below' />
</DialogContent>
</>;
return (
<>
<DialogContent className={classes.dialogContent}>
<Spinner label={locConstants.tableDesigner.publishingChanges} labelPosition='below' />
</DialogContent>
</>
);
}
if (metadata?.apiState?.publishState === LoadState.Loaded) {
return <>
<DialogContent className={classes.dialogContent}>
<div>Changes published successfully</div>
</DialogContent>
<DialogActions>
<Button size="medium" appearance="primary" onClick={designerContext.provider.closeDesigner}>Close Designer</Button>
<DialogTrigger action="close">
<Button size="medium" appearance="secondary" onClick={designerContext.provider.continueEditing}>Continue Editing</Button>
</DialogTrigger>
</DialogActions>
</>;
return (
<>
<DialogContent className={classes.dialogContent}>
<div>{locConstants.tableDesigner.changesPublishedSuccessfully}</div>
</DialogContent>
<DialogActions>
<Button size="medium" appearance="primary" onClick={designerContext.provider.closeDesigner}>{locConstants.tableDesigner.closeDesigner}</Button>
<DialogTrigger action="close">
<Button size="medium" appearance="secondary" onClick={designerContext.provider.continueEditing}>{locConstants.tableDesigner.continueEditing}</Button>
</DialogTrigger>
</DialogActions>
</>
);
}
if (metadata?.apiState?.previewState === LoadState.Loading) {
return <>
<DialogContent className={classes.dialogContent}>
<Spinner label="Loading" labelPosition='below' />
</DialogContent>
</>;
return (
<>
<DialogContent className={classes.dialogContent}>
<Spinner label={locConstants.tableDesigner.loadingTableDesigner} labelPosition='below' />
</DialogContent>
</>
);
}
if (metadata?.apiState?.previewState === LoadState.Error) {
return <>
<DialogContent className={classes.dialogContent}>
<ErrorCircleRegular className={classes.errorIcon} />
<div>Error loading preview</div>
<Button className={classes.retryButton} onClick={() => {
designerContext.provider.generatePreviewReport();
}}>Retry</Button>
</DialogContent>
</>;
return (
<>
<DialogContent className={classes.dialogContent}>
<ErrorCircleRegular className={classes.errorIcon} />
<div>{locConstants.tableDesigner.errorLoadingPreview}</div>
<Button className={classes.retryButton} onClick={() => {
designerContext.provider.generatePreviewReport();
}}>{locConstants.tableDesigner.retry}</Button>
</DialogContent>
</>
);
}
if (metadata?.apiState?.previewState === LoadState.Loaded) {
return <>
<DialogContent>
<div style={
{
width: '98%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
borderTop: '1px solid #e0e0e0',
borderBottom: '1px solid #e0e0e0',
overflow: 'auto',
}
}>
<ReactMarkdown>{metadata?.generatePreviewReportResult?.report}</ReactMarkdown>
</div>
</DialogContent>
<DialogActions>
<Button className={classes.updateDatabase} disabled={metadata.apiState?.previewState !== LoadState.Loaded} appearance="primary" onClick={() => {
designerContext.provider.publishChanges();
}} >Update Database</Button>
<DialogTrigger action="close">
<Button icon={generateScriptIcon()} iconPosition="after" className={classes.openScript} disabled={metadata.apiState?.previewState !== LoadState.Loaded} appearance="primary" onClick={designerContext.provider.generateScript} >Generate Script</Button>
</DialogTrigger>
<DialogTrigger disableButtonEnhancement>
<Button size="medium" appearance="secondary">Close</Button>
</DialogTrigger>
</DialogActions>
</>;
return (
<>
<DialogContent>
<div style={
{
width: '98%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
borderTop: '1px solid #e0e0e0',
borderBottom: '1px solid #e0e0e0',
overflow: 'auto',
}
}>
<ReactMarkdown>{metadata?.generatePreviewReportResult?.report}</ReactMarkdown>
</div>
</DialogContent>
<DialogActions>
<Button className={classes.updateDatabase} disabled={metadata.apiState?.previewState !== LoadState.Loaded} appearance="primary" onClick={() => {
designerContext.provider.publishChanges();
}} >{locConstants.tableDesigner.updateDatabase}</Button>
<DialogTrigger action="close">
<Button icon={generateScriptIcon()} iconPosition="after" className={classes.openScript} disabled={metadata.apiState?.previewState !== LoadState.Loaded} appearance="primary" onClick={designerContext.provider.generateScript} >{locConstants.tableDesigner.generateScript}</Button>
</DialogTrigger>
<DialogTrigger disableButtonEnhancement>
<Button size="medium" appearance="secondary">{locConstants.tableDesigner.close}</Button>
</DialogTrigger>
</DialogActions>
</>
);
}
};
return <Dialog inertTrapFocus={true}>
<DialogTrigger disableButtonEnhancement>
<ToolbarButton
aria-label="Publish"
title="Publish"
icon={<DatabaseArrowDownRegular />}
onClick ={() => {
designerContext.provider.generatePreviewReport();
}}
disabled={(metadata?.issues?.length ?? 0) > 0}
>
Publish
</ToolbarButton>
</DialogTrigger>
<DialogSurface>
<DialogBody>
<DialogTitle>
Preview Database Updates
</DialogTitle>
{getDialogContent()}
</DialogBody>
</DialogSurface>
</Dialog>
return (
<Dialog inertTrapFocus={true}>
<DialogTrigger disableButtonEnhancement>
<ToolbarButton
aria-label={locConstants.tableDesigner.publish}
title={locConstants.tableDesigner.publish}
icon={<DatabaseArrowDownRegular />}
onClick={() => {
designerContext.provider.generatePreviewReport();
}}
disabled={(metadata?.issues?.length ?? 0) > 0}
>
{locConstants.tableDesigner.publish}
</ToolbarButton>
</DialogTrigger>
<DialogSurface>
<DialogBody>
<DialogTitle>
{locConstants.tableDesigner.previewDatabaseUpdates}
</DialogTitle>
{getDialogContent()}
</DialogBody>
</DialogSurface>
</Dialog>
);
}

Просмотреть файл

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Button, makeStyles, shorthands } from "@fluentui/react-components";
import { Button, makeStyles } from "@fluentui/react-components";
import { AppsListDetailRegular, ChevronDownRegular, ChevronUpRegular } from "@fluentui/react-icons";
import React, { useState } from "react";
@ -21,12 +21,9 @@ const useStyles = makeStyles({
display: "flex",
flexDirection: "column",
overflowX: "hidden",
//...shorthands.border("1px solid #E5E5E5"),
...shorthands.borderWidth("1px"),
...shorthands.borderStyle("solid"),
...shorthands.borderColor("rgb(209, 209, 209)"),
...shorthands.borderRadius("8px"),
...shorthands.padding("12px"),
border: "1px solid rgb(209, 209, 209)",
borderRadius: "8px",
padding: "12px"
},
header: {
display: "flex",
@ -48,7 +45,7 @@ const useStyles = makeStyles({
textAlign: "left",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
...shorthands.overflow("hidden"),
overflow: "hidden",
width: "100%",
},
collapseButton: {
@ -56,7 +53,7 @@ const useStyles = makeStyles({
height: "20px",
lineHeight: "24px",
alignItems: "flex-start",
...shorthands.flex(1)
flex: 1
},
collapseIcon: {
width: "20px",

Просмотреть файл

@ -7,8 +7,9 @@ import { Tab, TabList } from "@fluentui/react-tabs"
import { CounterBadge, Text, makeStyles, shorthands } from "@fluentui/react-components";
import { TableDesignerContext } from "./tableDesignerStateProvider";
import { useContext } from "react";
import { DesignerMainPaneTabs, InputBoxProperties } from "../../../sharedInterfaces/tableDesigner";
import { DesignerMainPaneTabs, InputBoxProperties } from "../../../sharedInterfaces/tableDesigner";
import { DesignerMainPaneTab } from "./designerMainPaneTab";
import * as l10n from "@vscode/l10n";
const useStyles = makeStyles({
root: {
@ -36,8 +37,8 @@ const useStyles = makeStyles({
alignItems: 'center',
justifyContent: 'center',
'> *': {
marginRight: '5px'
},
marginRight: '5px'
},
}
});
@ -66,7 +67,46 @@ export const DesignerMainPane = () => {
}
}
return count;
};
function getTableIssuesCountLabel(id: string) {
const issues = getCurrentTabIssuesCount(id);
if (issues === 1) {
return l10n.t({
message: '{0} issue',
args: [issues],
comment: ['{0} is the number of issues']
});
} else if (issues > 1 || issues === 0) {
return l10n.t({
message: '{0} issues',
args: [issues],
comment: ['{0} is the number of issues']
});
}
}
function getTabAriaLabel(tabId: string) {
const issues = getCurrentTabIssuesCount(tabId);
if (issues === 0) {
return tabId;
} else if (issues === 1) {
return l10n.t({
message: '{0} {1} issue',
args: [tabId, issues],
comment: ['{0} is the tab name', '{1} is the number of issues']
});
} else {
return l10n.t({
message: '{0} {1} issues',
args: [tabId, issues],
comment: ['{0} is the tab name', '{1} is the number of issues']
});
}
}
return <div className={classes.root}>
<div className={classes.title}>
<Text className={classes.title} size={500} weight='semibold'>{(metadata.model!['name'] as InputBoxProperties).value}</Text>
@ -81,19 +121,16 @@ export const DesignerMainPane = () => {
>
{
metadata.view?.tabs.map(tab => {
const ariaLabel = `${tab.title} ${getCurrentTabIssuesCount(tab.id) > 0 ? getCurrentTabIssuesCount(tab.id) + ` issues` : ''} `;
return <Tab title={ariaLabel} value={tab.id} key={tab.id} onClick={() => {
//designerContext.clearPropertiesTabData();
}}>
<div className={classes.tabButtonContainer}
>
const ariaLabel = getTabAriaLabel(tab.id);
return <Tab title={ariaLabel} value={tab.id} key={tab.id}>
<div className={classes.tabButtonContainer}>
<Text>{tab.title}</Text>
{
getCurrentTabIssuesCount(tab.id) > 0 && <CounterBadge style={
{
marginTop: '2px'
}
} color="danger" size="small" title={getCurrentTabIssuesCount(tab.id) + ' issues'} count={getCurrentTabIssuesCount(tab.id)} />
} color="danger" size="small" title={getTableIssuesCountLabel(tab.id)} count={getCurrentTabIssuesCount(tab.id)} />
}
</div>
@ -110,7 +147,7 @@ export const DesignerMainPane = () => {
height: '100%',
}} key={tab.id}>
<DesignerMainPaneTab tabId={tab.id} />
</div>
</div>;
})
}
</div>

Просмотреть файл

@ -10,6 +10,7 @@ import { useContext } from "react";
import { TableDesignerContext } from "./tableDesignerStateProvider";
import { LoadState } from "../../../sharedInterfaces/tableDesigner";
import { DesignerChangesPreviewButton } from "./designerChangesPreviewButton";
import * as l10n from "@vscode/l10n";
const useStyles = makeStyles({
separator: {
@ -22,17 +23,19 @@ const useStyles = makeStyles({
export const DesignerPageRibbon = () => {
const designerContext = useContext(TableDesignerContext);
const classes = useStyles();
if (!designerContext) {
return null;
}
const GENERATE_SCRIPT = l10n.t('Generate Script');
const SCRIPT_AS_CREATE = l10n.t('Script As Create');
return (
<div>
<Toolbar size="small">
<ToolbarButton
aria-label="Generate Script"
title="Generate"
aria-label={GENERATE_SCRIPT}
title={GENERATE_SCRIPT}
icon={<DocumentChevronDoubleRegular />}
onClick={
() => {
@ -41,17 +44,19 @@ export const DesignerPageRibbon = () => {
}
disabled={(designerContext.state.issues?.length ?? 0) > 0}
>
Generate Script {designerContext.state.apiState?.generateScriptState === LoadState.Loading && <Spinner style={{
{GENERATE_SCRIPT} {designerContext.state.apiState?.generateScriptState === LoadState.Loading && <Spinner style={{
marginLeft: '5px'
}} size='extra-small' />}
</ToolbarButton>
<ToolbarButton
aria-label={SCRIPT_AS_CREATE}
title={SCRIPT_AS_CREATE}
icon={<DocumentChevronDoubleRegular />}
onClick={() => {
designerContext.provider.scriptAsCreate();
}}
>
Script As Create
{SCRIPT_AS_CREATE}
</ToolbarButton>
<DesignerChangesPreviewButton />
</Toolbar>

Просмотреть файл

@ -12,6 +12,7 @@ import { DesignerDropdown } from "./designerDropdown";
import { DesignerTable } from "./designerTable";
import { CheckBoxProperties, DesignerTableProperties, DropDownProperties, InputBoxProperties } from "../../../sharedInterfaces/tableDesigner";
import { DesignerCollapsibleDiv } from "./designerCollapsibleDiv";
import * as l10n from "@vscode/l10n";
const useStyles = makeStyles({
root: {
@ -59,19 +60,22 @@ export const DesignerPropertiesPane = () => {
const groups = Array.from(new Set(parentTableProperties.itemProperties?.filter(i => i.group).map(i => i.group)));
groups?.unshift('General');
const PROPERTIES = l10n.t('Properties');
const NO_DATA = l10n.t('No data');
if (!data) {
return <div className={classes.root}>
<Text className={classes.title} size={500}>Properties</Text>
<Text className={classes.title} size={500}>{PROPERTIES}</Text>
<div
className={classes.stack}
>
<Text>No data</Text>
<Text>{NO_DATA}</Text>
</div>
</div>
</div>;
}
return <div className={classes.root}>
<Text className={classes.title} size={500}>Properties</Text>
<Text className={classes.title} size={500}>{PROPERTIES}</Text>
<div
className={classes.stack}
>
@ -131,9 +135,9 @@ export const DesignerPropertiesPane = () => {
}
</div>
}
></DesignerCollapsibleDiv>
></DesignerCollapsibleDiv>;
})
}
</div>
</div>
</div>;
}

Просмотреть файл

@ -9,6 +9,7 @@ import { OpenFilled, ErrorCircleFilled, WarningFilled, InfoFilled } from "@fluen
import Editor from '@monaco-editor/react';
import { TableDesignerContext } from "./tableDesignerStateProvider";
import { DesignerIssue, DesignerResultPaneTabs, InputBoxProperties } from "../../../sharedInterfaces/tableDesigner";
import * as l10n from "@vscode/l10n";
const useStyles = makeStyles({
root: {
@ -68,8 +69,17 @@ export const DesignerResultPane = () => {
const state = useContext(TableDesignerContext);
const metadata = state?.state;
const getVscodeTheme = (theme: Theme) => {
const SEVERITY = l10n.t('Severity');
const DESCRIPTION = l10n.t('Description');
const SCRIPT_AS_CREATE = l10n.t('Script as CREATE');
const getIssuesTabAriaLabel = (count: number) => {
return count === 1 ? l10n.t('1 issue') : l10n.t('{0} issues', count);
};
const ISSUES = l10n.t('Issues');
const GO_THERE = l10n.t('Go there');
const OPEN_IN_NEW_TAB = l10n.t('Open in new tab');
const getVscodeTheme = (theme: Theme) => {
switch (theme) {
case webDarkTheme:
return 'vs-dark';
@ -83,11 +93,11 @@ export const DesignerResultPane = () => {
const columnsDef: TableColumnDefinition<DesignerIssue>[] = [
createTableColumn({
columnId: 'severity',
renderHeaderCell: () => <>Severity</>
renderHeaderCell: () => <>{SEVERITY}</>
}),
createTableColumn({
columnId: 'description',
renderHeaderCell: () => <>Description</>
renderHeaderCell: () => <>{DESCRIPTION}</>
}),
createTableColumn({
columnId: 'propertyPath',
@ -139,27 +149,27 @@ export const DesignerResultPane = () => {
className={classes.designerResultPaneTabs}
>
<Tab value={DesignerResultPaneTabs.Script} key={DesignerResultPaneTabs.Script}>
Script
{SCRIPT_AS_CREATE}
</Tab>
<Tab value={DesignerResultPaneTabs.Issues} key={DesignerResultPaneTabs.Issues}
disabled={!metadata.issues || metadata.issues.length === 0}
aria-label={getIssuesTabAriaLabel(metadata.issues?.length!)}
>
Issues {metadata.issues && <CounterBadge style={{
{ISSUES} {metadata.issues && <CounterBadge style={{
marginLeft: '5px',
marginTop: '-10px'
}} count={metadata.issues?.length} size='small' />}
</Tab>
</TabList>
{
metadata.tabStates!.resultPaneTab == DesignerResultPaneTabs.Script &&
metadata.tabStates!.resultPaneTab === DesignerResultPaneTabs.Script &&
<Divider vertical style={{
flex: '0'
}} />
}
{
metadata.tabStates!.resultPaneTab == DesignerResultPaneTabs.Script &&
<Button appearance="transparent" icon={<OpenFilled />} onClick={() => state.provider.scriptAsCreate()} title='Open in new tab'></Button>
metadata.tabStates!.resultPaneTab === DesignerResultPaneTabs.Script &&
<Button appearance="transparent" icon={<OpenFilled />} onClick={() => state.provider.scriptAsCreate()} title={OPEN_IN_NEW_TAB}></Button>
}
</div>
<div className={classes.tabContent}>
@ -212,25 +222,12 @@ export const DesignerResultPane = () => {
<TableCell
{...columnSizing_unstable.getTableCellProps('propertyPath')}
><Link>
Go there
{GO_THERE}
</Link></TableCell>
</TableRow>
})
}
</TableBody>
{/* {metadata.issues?.map((i, index) => {
return <div className={classes.issuesRows}>
<Text size={300}>{(index + 1)}.</Text>
<Text size={300}>{i.description} : {i.propertyPath?.join('.')}</Text>
<Link onClick={() => {
console.log('Go there');
//designerContext.goToProperty(i.propertyPath!);
}}>
Go there
</Link>
{i.moreInfoLink && <Link href={i.moreInfoLink} target="_blank">More info</Link>}
</div>
})} */}
</Table>
</div>
}

Просмотреть файл

@ -13,6 +13,7 @@ import { TableDesignerContext } from "./tableDesignerStateProvider";
import { DesignerCheckbox } from "./designerCheckbox";
import { DesignerDropdown } from "./designerDropdown";
import { DesignerInputBox } from "./designerInputBox";
import * as l10n from "@vscode/l10n";
export type DesignerTableProps = {
component: designer.DesignerDataPropertyInfo,
@ -33,8 +34,6 @@ const useStyles = fluentui.makeStyles({
}
});
// Hello
export const DesignerTable = ({
component,
model,
@ -45,6 +44,10 @@ export const DesignerTable = ({
const tableProps = component.componentProperties as designer.DesignerTableProperties;
const state = useContext(TableDesignerContext);
const classes = useStyles();
const MOVE_UP = l10n.t('Move Up');
const MOVE_DOWN = l10n.t('Move Down');
const columnsDef: fluentui.TableColumnDefinition<designer.DesignerTableComponentDataItem>[] = tableProps.columns!.map((column) => {
const colProps = tableProps.itemProperties?.find(item => item.propertyName === column);
return fluentui.createTableColumn(
@ -62,7 +65,10 @@ export const DesignerTable = ({
if (tableProps.canRemoveRows) {
columnsDef.push(fluentui.createTableColumn({
columnId: 'remove',
renderHeaderCell: () => <>Delete</>
renderHeaderCell: () => {
const DELETE = l10n.t('Delete');
return <>{DELETE}</>;
}
}));
}
@ -254,7 +260,7 @@ export const DesignerTable = ({
}}
disabled={focusedRowId === undefined || focusedRowId === 0}
>
Move Up
{MOVE_UP}
</fluentui.ToolbarButton>
}
{
@ -267,13 +273,13 @@ export const DesignerTable = ({
}}
disabled={focusedRowId === undefined || focusedRowId === rows.length - 1}
>
Move Down
{MOVE_DOWN}
</fluentui.ToolbarButton>
}
</fluentui.Toolbar>
<fluentui.Table
as = "table"
as="table"
size="small"
{...columnSizing_unstable.getTableProps()}
ref={tableRef}

Просмотреть файл

@ -13,6 +13,7 @@ import { DesignerPageRibbon } from "./designerPageRibbon";
import { DesignerMainPane } from "./designerMainPane";
import { DesignerPropertiesPane } from "./designerPropertiesPane";
import { DesignerResultPane } from "./designerResultPane";
import * as l10n from "@vscode/l10n";
const useStyles = makeStyles({
root: {
@ -101,20 +102,25 @@ export const TableDesigner = () => {
if (!tableDesignerState) {
return null;
}
const ERROR_LOADING_DESIGNER = l10n.t('Error loading designer');
const RETRY = l10n.t('Retry');
const LOADING_TABLE_DESIGNER = l10n.t('Loading table designer');
return (
<div className={classes.root}>
{
tableDesignerState.apiState?.initializeState === designer.LoadState.Loading &&
<div className={classes.pageContext}>
<Spinner label='Loading...' labelPosition="below" />
<Spinner label={LOADING_TABLE_DESIGNER} labelPosition="below" />
</div>
}
{
tableDesignerState.apiState?.initializeState === designer.LoadState.Error &&
<div className={classes.pageContext}>
<ErrorCircleRegular className={classes.errorIcon} />
<div>Error loading designer</div>
<Button className={classes.retryButton}>Retry</Button>
<div>{ERROR_LOADING_DESIGNER}</div>
<Button className={classes.retryButton}>{RETRY}</Button>
</div>
}
{

Просмотреть файл

@ -20,6 +20,7 @@ export interface ObjectExplorerReducers {
}
export interface ObjectExplorerFilterContextProps {
isLocalizationLoaded: boolean;
state: ObjectExplorerFilterState | undefined;
theme: Theme;
submit: (filters: vscodeMssql.NodeFilter[]) => void;

Просмотреть файл

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as designer from '../sharedInterfaces/tableDesigner';
import * as vscode from 'vscode';
export function getAboutTableComponents(viewDefinition: designer.TableDesignerView | undefined): designer.DesignerDataPropertyInfo[] {
if (!viewDefinition) {
@ -13,27 +14,27 @@ export function getAboutTableComponents(viewDefinition: designer.TableDesignerVi
{
componentType: 'input',
propertyName: designer.TableColumnProperty.Name,
description: "The name of the table object.",
description: vscode.l10n.t("The name of the table object."),
componentProperties: {
title: "Table name",
title: vscode.l10n.t("Table name"),
width: 350
}
},
{
componentType: 'dropdown',
propertyName: designer.TableProperty.Schema,
description: "The schema that contains the table.",
description: vscode.l10n.t("The schema that contains the table."),
componentProperties: {
title: "Schema",
title: vscode.l10n.t("Schema"),
width: 350,
}
},
{
componentType: 'textarea',
propertyName: designer.TableProperty.Description,
description: "Description for the table.",
description: vscode.l10n.t("Description for the table."),
componentProperties: {
title: "Description",
title: vscode.l10n.t("Description"),
width: 350
}
}
@ -57,25 +58,25 @@ export function getColumnsTabComponents(view: designer.TableDesignerView | undef
{
componentType: 'input',
propertyName: designer.TableColumnProperty.Name,
description: "The name of the column object.",
description: vscode.l10n.t("The name of the column object."),
componentProperties: {
title: "Name",
title: vscode.l10n.t("Name"),
width: 150
}
}, {
componentType: 'input',
propertyName: designer.TableColumnProperty.Description,
description: "Displays the description of the column",
description: vscode.l10n.t("Displays the description of the column"),
componentProperties: {
title: "Description",
title: vscode.l10n.t("Description"),
width: 400
}
}, {
componentType: 'dropdown',
propertyName: designer.TableColumnProperty.AdvancedType,
description: "Displays the unified data type (including length, scale and precision) for the column",
description: vscode.l10n.t("Displays the unified data type (including length, scale and precision) for the column"),
componentProperties: {
title: "Advanced Type",
title: vscode.l10n.t("Advanced Type"),
width: 120,
isEditable: true
}
@ -83,56 +84,56 @@ export function getColumnsTabComponents(view: designer.TableDesignerView | undef
componentType: 'dropdown',
propertyName: designer.TableColumnProperty.Type,
showInPropertiesView: false,
description: "Displays the data type name for the column",
description: vscode.l10n.t("Displays the data type name for the column"),
componentProperties: {
title: "Type",
title: vscode.l10n.t("Type"),
width: 100
}
}, {
componentType: 'input',
propertyName: designer.TableColumnProperty.Length,
description: "The maximum length (in characters) that can be stored in this database object.",
description: vscode.l10n.t("The maximum length (in characters) that can be stored in this database object."),
componentProperties: {
title: "Length",
title: vscode.l10n.t("Length"),
width: 60
}
}, {
componentType: 'input',
propertyName: designer.TableColumnProperty.DefaultValue,
description: "A predefined global default value for the column or binding.",
description: vscode.l10n.t("A predefined global default value for the column or binding."),
componentProperties: {
title: "Default Value",
title: vscode.l10n.t("Default Value"),
width: 150
}
}, {
componentType: 'checkbox',
propertyName: designer.TableColumnProperty.AllowNulls,
description: "Specifies whether the column may have a NULL value.",
description: vscode.l10n.t("Specifies whether the column may have a NULL value."),
componentProperties: {
title: "Allow Nulls",
title: vscode.l10n.t("Allow Nulls"),
}
}, {
componentType: 'checkbox',
propertyName: designer.TableColumnProperty.IsPrimaryKey,
description: "Specifies whether the column is included in the primary key for the table.",
description: vscode.l10n.t("Specifies whether the column is included in the primary key for the table."),
componentProperties: {
title: "Primary Key",
title: vscode.l10n.t("Primary Key"),
}
}, {
componentType: 'input',
propertyName: designer.TableColumnProperty.Precision,
description: "For numeric data, the maximum number of decimal digits that can be stored in this database object.",
description: vscode.l10n.t("For numeric data, the maximum number of decimal digits that can be stored in this database object."),
componentProperties: {
title: "Precision",
title: vscode.l10n.t("Precision"),
width: 60,
inputType: designer.InputType.Number
}
}, {
componentType: 'input',
propertyName: designer.TableColumnProperty.Scale,
description: "For numeric data, the maximum number of decimal digits that can be stored in this database object to the right of decimal point.",
description: vscode.l10n.t("For numeric data, the maximum number of decimal digits that can be stored in this database object to the right of decimal point."),
componentProperties: {
title: "Scale",
title: vscode.l10n.t("Scale"),
width: 60,
inputType: designer.InputType.Number
}
@ -141,7 +142,7 @@ export function getColumnsTabComponents(view: designer.TableDesignerView | undef
const displayProperties = getTableDisplayProperties(columnTableOptions, [
designer.TableColumnProperty.Name,
designer.TableColumnProperty.AdvancedType,
designer.TableColumnProperty.Type,
designer.TableColumnProperty.IsPrimaryKey,
designer.TableColumnProperty.AllowNulls,
designer.TableColumnProperty.DefaultValue,
@ -153,23 +154,23 @@ export function getColumnsTabComponents(view: designer.TableDesignerView | undef
propertyName: designer.TableProperty.Columns,
showInPropertiesView: false,
componentProperties: {
ariaLabel: "Columns",
ariaLabel: vscode.l10n.t("Columns"),
columns: displayProperties,
itemProperties: addAdditionalTableProperties(columnTableOptions, columnTableColumnDefinitions),
objectTypeDisplayName: "Column",
objectTypeDisplayName: vscode.l10n.t("Column"),
canAddRows: columnTableOptions.canAddRows,
canInsertRows: columnTableOptions.canInsertRows,
canMoveRows: columnTableOptions.canMoveRows,
canRemoveRows: columnTableOptions.canRemoveRows,
removeRowConfirmationMessage: columnTableOptions.removeRowConfirmationMessage,
showRemoveRowConfirmation: columnTableOptions.showRemoveRowConfirmation,
labelForAddNewButton: columnTableOptions.labelForAddNewButton ?? "New Column"
labelForAddNewButton: columnTableOptions.labelForAddNewButton ?? vscode.l10n.t("New Column")
} as designer.DesignerTableProperties
},
];
const additionalComponents = getAdditionalComponentsForTab(designer.TableProperty.Columns, view.additionalComponents);
if(additionalComponents) {
if (additionalComponents) {
tabComponents.push(...additionalComponents);
}
return tabComponents;
@ -183,9 +184,9 @@ export function getPrimaryKeyTabComponents(view: designer.TableDesignerView | un
{
componentType: 'dropdown',
propertyName: designer.TableIndexColumnSpecificationProperty.Column,
description: "The name of the column.",
description: vscode.l10n.t("The name of the column."),
componentProperties: {
title: "Column",
title: vscode.l10n.t("Column"),
width: 150
}
}
@ -196,9 +197,9 @@ export function getPrimaryKeyTabComponents(view: designer.TableDesignerView | un
componentType: 'input',
propertyName: designer.TableProperty.PrimaryKeyName,
showInPropertiesView: false,
description: "Name of the primary key.",
description: vscode.l10n.t("Name of the primary key."),
componentProperties: {
title: "Name",
title: vscode.l10n.t("Name"),
width: 250
}
},
@ -206,9 +207,9 @@ export function getPrimaryKeyTabComponents(view: designer.TableDesignerView | un
componentType: 'textarea',
propertyName: designer.TableProperty.PrimaryKeyDescription,
showInPropertiesView: false,
description: "The description of the primary key.",
description: vscode.l10n.t("The description of the primary key."),
componentProperties: {
title: "Description",
title: vscode.l10n.t("Description"),
width: 250
}
}
@ -228,10 +229,10 @@ export function getPrimaryKeyTabComponents(view: designer.TableDesignerView | un
componentType: 'table',
propertyName: designer.TableProperty.PrimaryKeyColumns,
showInPropertiesView: false,
description: "Columns in the primary key.",
description: vscode.l10n.t("Columns in the primary key."),
componentProperties: {
title: "Primary Key Columns",
ariaLabel: "Primary Key Columns",
title: vscode.l10n.t("Primary Key Columns"),
ariaLabel: vscode.l10n.t("Primary Key Columns"),
columns: getTableDisplayProperties(primaryKeyTableOptions, [designer.TableIndexColumnSpecificationProperty.Column]),
itemProperties: addAdditionalTableProperties(primaryKeyTableOptions, columnSpecProperties),
objectTypeDisplayName: '',
@ -240,14 +241,14 @@ export function getPrimaryKeyTabComponents(view: designer.TableDesignerView | un
removeRowConfirmationMessage: primaryKeyTableOptions.removeRowConfirmationMessage,
showRemoveRowConfirmation: primaryKeyTableOptions.showRemoveRowConfirmation,
showItemDetailInPropertiesView: false,
labelForAddNewButton: primaryKeyTableOptions.labelForAddNewButton ?? "Add Column",
labelForAddNewButton: primaryKeyTableOptions.labelForAddNewButton ?? vscode.l10n.t("Add Column"),
canMoveRows: primaryKeyTableOptions.canMoveRows
} as designer.DesignerTableProperties
});
}
const additionalComponents = getAdditionalComponentsForTab(designer.TableProperty.PrimaryKey, view.additionalComponents);
if(additionalComponents) {
if (additionalComponents) {
tabComponents.push(...additionalComponents);
}
return tabComponents;
@ -263,9 +264,9 @@ export function getIndexesTabComponents(view: designer.TableDesignerView | undef
{
componentType: 'dropdown',
propertyName: designer.TableIndexColumnSpecificationProperty.Column,
description: "The name of the column.",
description: vscode.l10n.t("The name of the column."),
componentProperties: {
title: "Column",
title: vscode.l10n.t("Column"),
width: 100
}
}];
@ -273,17 +274,17 @@ export function getIndexesTabComponents(view: designer.TableDesignerView | undef
{
componentType: 'input',
propertyName: designer.TableIndexProperty.Name,
description: "The name of the index.",
description: vscode.l10n.t("The name of the index."),
componentProperties: {
title: "Name",
title: vscode.l10n.t("Name"),
width: 200
}
}, {
componentType: 'input',
propertyName: designer.TableIndexProperty.Description,
description: "The description of the index.",
description: vscode.l10n.t("The description of the index."),
componentProperties: {
title: "Description",
title: vscode.l10n.t("Description"),
width: 200
}
}
@ -294,10 +295,10 @@ export function getIndexesTabComponents(view: designer.TableDesignerView | undef
{
componentType: 'table',
propertyName: designer.TableIndexProperty.Columns,
description: "The columns of the index.",
group: "Columns",
description: vscode.l10n.t("The columns of the index."),
group: vscode.l10n.t("Columns"),
componentProperties: {
ariaLabel: "Columns",
ariaLabel: vscode.l10n.t("Columns"),
columns: getTableDisplayProperties(columnSpecTableOptions, [designer.TableIndexColumnSpecificationProperty.Column]),
itemProperties: addAdditionalTableProperties(columnSpecTableOptions, columnSpecProperties),
objectTypeDisplayName: '',
@ -305,7 +306,7 @@ export function getIndexesTabComponents(view: designer.TableDesignerView | undef
canRemoveRows: columnSpecTableOptions.canRemoveRows,
removeRowConfirmationMessage: columnSpecTableOptions.removeRowConfirmationMessage,
showRemoveRowConfirmation: columnSpecTableOptions.showRemoveRowConfirmation,
labelForAddNewButton: columnSpecTableOptions.labelForAddNewButton ?? "Add Column"
labelForAddNewButton: columnSpecTableOptions.labelForAddNewButton ?? vscode.l10n.t("Add Column")
} as designer.DesignerTableProperties
}
);
@ -313,27 +314,27 @@ export function getIndexesTabComponents(view: designer.TableDesignerView | undef
const tabComponents: designer.DesignerDataPropertyInfo[] = [];
if(indexTableOptions) {
if (indexTableOptions) {
tabComponents.push({
componentType: 'table',
propertyName: designer.TableProperty.Indexes,
showInPropertiesView: false,
componentProperties: {
ariaLabel: "Indexes",
ariaLabel: vscode.l10n.t("Indexes"),
columns: getTableDisplayProperties(indexTableOptions, [designer.TableIndexProperty.Name]),
itemProperties: addAdditionalTableProperties(indexTableOptions, indexProperties),
objectTypeDisplayName: "Index",
objectTypeDisplayName: vscode.l10n.t("Index"),
canAddRows: indexTableOptions.canAddRows,
canRemoveRows: indexTableOptions.canRemoveRows,
removeRowConfirmationMessage: indexTableOptions.removeRowConfirmationMessage,
showRemoveRowConfirmation: indexTableOptions.showRemoveRowConfirmation,
labelForAddNewButton: indexTableOptions.labelForAddNewButton ?? "New Index"
labelForAddNewButton: indexTableOptions.labelForAddNewButton ?? vscode.l10n.t("New Index")
} as designer.DesignerTableProperties
});
}
const additionalComponents = getAdditionalComponentsForTab(designer.TableProperty.Indexes, view.additionalComponents);
if(additionalComponents) {
if (additionalComponents) {
tabComponents.push(...additionalComponents);
}
return tabComponents;
@ -350,7 +351,7 @@ export function getForeignKeysTabComponents(view: designer.TableDesignerView | u
componentType: 'dropdown',
propertyName: designer.ForeignKeyColumnMappingProperty.ForeignColumn,
componentProperties: {
title: "Foreign Column",
title: vscode.l10n.t("Foreign Column"),
width: 150
}
},
@ -358,7 +359,7 @@ export function getForeignKeysTabComponents(view: designer.TableDesignerView | u
componentType: 'dropdown',
propertyName: designer.ForeignKeyColumnMappingProperty.Column,
componentProperties: {
title: "Column",
title: vscode.l10n.t("Column"),
width: 150
}
},
@ -368,44 +369,44 @@ export function getForeignKeysTabComponents(view: designer.TableDesignerView | u
{
componentType: 'input',
propertyName: designer.TableForeignKeyProperty.Name,
description: "The name of the foreign key.",
description: vscode.l10n.t("The name of the foreign key."),
componentProperties: {
title: "Name",
title: vscode.l10n.t("Name"),
width: 300
}
},
{
componentType: 'input',
propertyName: designer.TableForeignKeyProperty.Description,
description: "The description of the foreign key.",
description: vscode.l10n.t("The description of the foreign key."),
componentProperties: {
title: "Description",
title: vscode.l10n.t("Description"),
}
},
{
componentType: 'dropdown',
propertyName: designer.TableForeignKeyProperty.ForeignTable,
description: "The table which contains the primary or unique key column.",
description: vscode.l10n.t("The table which contains the primary or unique key column."),
componentProperties: {
title: "Foreign Table",
title: vscode.l10n.t("Foreign Table"),
width: 200
}
},
{
componentType: 'dropdown',
propertyName: designer.TableForeignKeyProperty.OnUpdateAction,
description: "The behavior when a user tries to update a row with data that is involved in a foreign key relationship.",
description: vscode.l10n.t("The behavior when a user tries to update a row with data that is involved in a foreign key relationship."),
componentProperties: {
title: "On Update Action",
title: vscode.l10n.t("On Update Action"),
width: 100
}
},
{
componentType: 'dropdown',
propertyName: designer.TableForeignKeyProperty.OnDeleteAction,
description: "The behavior when a user tries to delete a row with data that is involved in a foreign key relationship.",
description: vscode.l10n.t("The behavior when a user tries to delete a row with data that is involved in a foreign key relationship."),
componentProperties: {
title: "On Delete Action",
title: vscode.l10n.t("On Delete Action"),
width: 100
}
},
@ -416,16 +417,16 @@ export function getForeignKeysTabComponents(view: designer.TableDesignerView | u
foreignKeyProperties.push({
componentType: 'table',
propertyName: designer.TableForeignKeyProperty.Columns,
description: "The mapping between foreign key columns and primary key columns.",
group: "Columns",
description: vscode.l10n.t("The mapping between foreign key columns and primary key columns."),
group: vscode.l10n.t("Columns"),
componentProperties: {
ariaLabel: "Columns",
ariaLabel: vscode.l10n.t("Columns"),
columns: getTableDisplayProperties(columnMappingTableOptions, [designer.ForeignKeyColumnMappingProperty.Column, designer.ForeignKeyColumnMappingProperty.ForeignColumn]),
itemProperties: addAdditionalTableProperties(columnMappingTableOptions, foreignKeyColumnMappingProperties),
canAddRows: columnMappingTableOptions.canAddRows,
canRemoveRows: columnMappingTableOptions.canRemoveRows,
removeRowConfirmationMessage: columnMappingTableOptions.removeRowConfirmationMessage,
labelForAddNewButton: columnMappingTableOptions.labelForAddNewButton ?? "New Column Mapping"
labelForAddNewButton: columnMappingTableOptions.labelForAddNewButton ?? vscode.l10n.t("New Column Mapping")
} as designer.DesignerTableProperties
});
}
@ -438,28 +439,28 @@ export function getForeignKeysTabComponents(view: designer.TableDesignerView | u
propertyName: designer.TableProperty.ForeignKeys,
showInPropertiesView: false,
componentProperties: {
ariaLabel: "Foreign Keys",
ariaLabel: vscode.l10n.t("Foreign Keys"),
columns: getTableDisplayProperties(foreignKeyTableOptions, [designer.TableForeignKeyProperty.Name, designer.TableForeignKeyProperty.ForeignTable]),
itemProperties: addAdditionalTableProperties(foreignKeyTableOptions, foreignKeyProperties),
objectTypeDisplayName: "Foreign Key",
objectTypeDisplayName: vscode.l10n.t("Foreign Key"),
canAddRows: foreignKeyTableOptions.canAddRows,
canRemoveRows: foreignKeyTableOptions.canRemoveRows,
removeRowConfirmationMessage: foreignKeyTableOptions.removeRowConfirmationMessage,
showRemoveRowConfirmation: foreignKeyTableOptions.showRemoveRowConfirmation,
labelForAddNewButton: foreignKeyTableOptions.labelForAddNewButton ?? "New Foreign Key"
labelForAddNewButton: foreignKeyTableOptions.labelForAddNewButton ?? vscode.l10n.t("New Foreign Key")
} as designer.DesignerTableProperties
});
}
const additionalComponents = getAdditionalComponentsForTab(designer.TableProperty.ForeignKeys, view.additionalComponents);
if(additionalComponents) {
if (additionalComponents) {
tabComponents.push(...additionalComponents);
}
return tabComponents;
}
export function getCheckConstraintsTabComponents(view: designer.TableDesignerView | undefined): designer.DesignerDataPropertyInfo[] {
if(!view || !view.checkConstraintTableOptions) {
if (!view || !view.checkConstraintTableOptions) {
return [];
}
const checkConstraintTableOptions = view.checkConstraintTableOptions;
@ -468,24 +469,24 @@ export function getCheckConstraintsTabComponents(view: designer.TableDesignerVie
{
componentType: 'input',
propertyName: designer.TableCheckConstraintProperty.Name,
description: "The name of the check constraint.",
description: vscode.l10n.t("The name of the check constraint."),
componentProperties: {
title: "Name",
title: vscode.l10n.t("Name"),
width: 200
}
}, {
componentType: 'input',
propertyName: designer.TableCheckConstraintProperty.Description,
description: "The description of the check constraint.",
description: vscode.l10n.t("The description of the check constraint."),
componentProperties: {
title: "Description",
title: vscode.l10n.t("Description"),
}
}, {
componentType: 'input',
propertyName: designer.TableCheckConstraintProperty.Expression,
description: "The expression defining the check constraint.",
description: vscode.l10n.t("The expression defining the check constraint."),
componentProperties: {
title: "Expression",
title:vscode.l10n.t("Expression"),
width: 300
}
}
@ -493,67 +494,67 @@ export function getCheckConstraintsTabComponents(view: designer.TableDesignerVie
const tabComponents: designer.DesignerDataPropertyInfo[] = [];
if(checkConstraintTableOptions) {
if (checkConstraintTableOptions) {
tabComponents.push({
componentType: 'table',
propertyName: designer.TableProperty.CheckConstraints,
showInPropertiesView: false,
componentProperties: {
ariaLabel: "Check Constraints",
ariaLabel: vscode.l10n.t("Check Constraints"),
columns: getTableDisplayProperties(checkConstraintTableOptions, [designer.TableCheckConstraintProperty.Name, designer.TableCheckConstraintProperty.Expression]),
itemProperties: addAdditionalTableProperties(checkConstraintTableOptions, checkConstraintProperties),
objectTypeDisplayName: "Check Constraint",
objectTypeDisplayName: vscode.l10n.t("Check Constraint"),
canAddRows: checkConstraintTableOptions.canAddRows,
canRemoveRows: checkConstraintTableOptions.canRemoveRows,
removeRowConfirmationMessage: checkConstraintTableOptions.removeRowConfirmationMessage,
showRemoveRowConfirmation: checkConstraintTableOptions.showRemoveRowConfirmation,
labelForAddNewButton: checkConstraintTableOptions.labelForAddNewButton ?? "New Check Constraint"
labelForAddNewButton: checkConstraintTableOptions.labelForAddNewButton ?? vscode.l10n.t("New Check Constraint")
} as designer.DesignerTableProperties
});
}
const additionalComponents = getAdditionalComponentsForTab(designer.TableProperty.CheckConstraints, additionalcomponents);
if(additionalComponents) {
if (additionalComponents) {
tabComponents.push(...additionalComponents);
}
return tabComponents;
}
export function getDesignerView(view: designer.TableDesignerView | undefined): designer.DesignerView {
return {
tabs: [
{
title: "About table",
id: designer.DesignerMainPaneTabs.AboutTable,
components: getAboutTableComponents(view)
},
{
title: "Columns",
id: designer.DesignerMainPaneTabs.Columns,
components: getColumnsTabComponents(view)
},
{
title: "Primary Key",
id: designer.DesignerMainPaneTabs.PrimaryKey,
components: getPrimaryKeyTabComponents(view)
},
{
title: "Indexes",
id: designer.DesignerMainPaneTabs.Indexes,
components: getIndexesTabComponents(view)
},
{
title: "Foreign Keys",
id: designer.DesignerMainPaneTabs.ForeignKeys,
components: getForeignKeysTabComponents(view)
},
{
title: "Check Constraints",
id: designer.DesignerMainPaneTabs.CheckConstraints,
components: getCheckConstraintsTabComponents(view)
}
]
};
return {
tabs: [
{
title: vscode.l10n.t("About table"),
id: designer.DesignerMainPaneTabs.AboutTable,
components: getAboutTableComponents(view)
},
{
title: vscode.l10n.t("Columns"),
id: designer.DesignerMainPaneTabs.Columns,
components: getColumnsTabComponents(view)
},
{
title: vscode.l10n.t("Primary Key"),
id: designer.DesignerMainPaneTabs.PrimaryKey,
components: getPrimaryKeyTabComponents(view)
},
{
title: vscode.l10n.t("Indexes"),
id: designer.DesignerMainPaneTabs.Indexes,
components: getIndexesTabComponents(view)
},
{
title: vscode.l10n.t("Foreign Keys"),
id: designer.DesignerMainPaneTabs.ForeignKeys,
components: getForeignKeysTabComponents(view)
},
{
title: vscode.l10n.t("Check Constraints"),
id: designer.DesignerMainPaneTabs.CheckConstraints,
components: getCheckConstraintsTabComponents(view)
}
]
};
}
@ -576,13 +577,4 @@ function getAdditionalComponentsForTab(tabId: designer.TableProperty, additional
return additionalComponents.filter(c => c.tab === tabId);
}
return [];
}
export function getIssuesForComponent(componentPath: designer.DesignerPropertyPath, issues: designer.DesignerIssue[]): string {
if (!issues || issues.length === 0) {
return "";
}
return issues.filter(i => i.propertyPath?.toString() === componentPath.toString()).reduce((acc, issue) => {
return acc + issue.description + " ";
}, "");
}

Просмотреть файл

@ -50,13 +50,16 @@ async function getL10nJson() {
for (const file of tsFiles) {
const content = await fs.readFile(path.resolve('./src', file), 'utf8');
if (content) {
fileContents.push(content);
fileContents.push({
contents: content,
extension: file.endsWith('.tsx') ? '.tsx' : '.ts'
});
}
}
const result = await vscodel10n.getL10nJson(fileContents.map(f => {
return {
contents: f,
extension: '.ts'
contents: f.contents,
extension: f.extension
};
}));
return result;